// get the bitmaps border - that is where the black parts start private bool GetBitmapBorder(Bitmap bitmap, BitmapBorder border, int interCharSpacing) { // search for first column (x) from the left to contain data for (border.leftX = 0; border.leftX < bitmap.Width; border.leftX++) { // if set pixels found, stop looking if (this.BitmapColumnIsEmpty(bitmap, border.leftX) == false) { break; } } // search for first column (x) from the right to contain data for (border.rightX = bitmap.Width - 1; border.rightX >= 0; border.rightX--) { // if set pixels found, stop looking if (this.BitmapColumnIsEmpty(bitmap, border.rightX) == false) { break; } } // set top border at 0 border.topY = 0; // search for first row (y) from the bottom to contain data for (border.bottomY = bitmap.Height - 1; border.bottomY >= 0; border.bottomY--) { // if set pixels found, stop looking if (this.BitmapRowIsEmpty(bitmap, border.bottomY) == false) { break; } } // check if the bitmap contains any black pixels if (border.rightX == -1) { // no pixels were found return(false); } // add inter-character spacing border.rightX += interCharSpacing; return(true); }
// iterate through the original bitmaps and find the tightest common border private void FindTightestCommonBitmapBorder(CharacterGenerationInfo[] charInfoArray, BitmapBorder tightestBorder) { // iterate through bitmaps for (int charIdx = 0; charIdx < charInfoArray.Length; ++charIdx) { // create a border BitmapBorder bitmapBorder = new BitmapBorder(); // get the bitmaps border this.GetBitmapBorder(charInfoArray[charIdx].BitmapOriginal, bitmapBorder, 0); // check if we need to loosen up the tightest border tightestBorder.leftX = Math.Min(bitmapBorder.leftX, tightestBorder.leftX); tightestBorder.topY = Math.Min(bitmapBorder.topY, tightestBorder.topY); tightestBorder.rightX = Math.Max(bitmapBorder.rightX, tightestBorder.rightX); tightestBorder.bottomY = Math.Max(bitmapBorder.bottomY, tightestBorder.bottomY); } }
// generate the required output for image private void generateOutputForImage(ref Bitmap bitmapOriginal, ref string resultTextSource, ref string resultTextHeader) { // the name of the bitmap string imageName = scrubVariableName(txtImageName.Text); // check if bitmap is assigned if (m_currentLoadedBitmap != null) { // // Bitmap manipulation // // get bitmap border BitmapBorder bitmapBorder = new BitmapBorder(); getBitmapBorder(bitmapOriginal, bitmapBorder); // manipulate the bitmap Bitmap bitmapManipulated; // try to manipulate teh bitmap if (!manipulateBitmap(bitmapOriginal, bitmapBorder, out bitmapManipulated, 0, 0)) { // show error MessageBox.Show("No black pixels found in bitmap (currently only monochrome bitmaps supported)", "Can't convert bitmap", MessageBoxButtons.OK, MessageBoxIcon.Error); // stop here, failed to manipulate the bitmap for whatever reason return; } // for debugging // bitmapManipulated.Save(String.Format("C:/bms/manip.bmp")); // according to config if (m_outputConfig.commentVariableName) { // add source file header resultTextSource += String.Format("{0}" + nl+"{1} Image data for {2}" + nl+"{3}" + nl + nl, m_commentStartString, m_commentBlockMiddleString, imageName, m_commentBlockEndString); // add header file header resultTextHeader += String.Format("{0}Bitmap info for {1}{2}" + nl, m_commentStartString, imageName, m_commentEndString); } // bitmap varname string dataVarName = String.Format(m_outputConfig.varNfBitmaps, imageName); // add to header resultTextHeader += String.Format("extern {0};" + nl, dataVarName); // add header resultTextSource += String.Format("{0} =" + nl+"{{" + nl, dataVarName); // // Bitmap to string // // page array ArrayList pages; // first convert to pages convertBitmapToPageArray(bitmapManipulated, out pages); // assign pages for fully populated 8 bits int pagesPerRow = convertValueByDescriptorFormat(OutputConfiguration.DescriptorFormat.DisplayInBytes, bitmapManipulated.Width); // now convert to string resultTextSource += generateStringFromPageArray(bitmapManipulated.Width, bitmapManipulated.Height, pages); // close resultTextSource += String.Format("}};" + nl + nl); // according to config if (m_outputConfig.commentVariableName) { // set sizes comment resultTextSource += String.Format("{0}Bitmap sizes for {1}{2}" + nl, m_commentStartString, imageName, m_commentEndString); } // get var name string heightVarName = String.Format(m_outputConfig.varNfHeight, imageName); string widthVarName = String.Format(m_outputConfig.varNfWidth, imageName); // display width in bytes? if (m_outputConfig.descImgWidth == OutputConfiguration.DescriptorFormat.DisplayInBytes) { // in pages resultTextSource += String.Format("{0}Pages = {1};" + nl, widthVarName, pagesPerRow); resultTextHeader += String.Format("extern {0}Pages;" + nl, widthVarName); } else { // in pixels resultTextSource += String.Format("{0}Pixels = {1};" + nl, widthVarName, bitmapManipulated.Width); resultTextHeader += String.Format("extern {0}Pixels;" + nl, widthVarName); } // display height in bytes? if (m_outputConfig.descImgHeight == OutputConfiguration.DescriptorFormat.DisplayInBytes) { // in pages resultTextSource += String.Format("{0}Pages = {1};" + nl, heightVarName, convertValueByDescriptorFormat(OutputConfiguration.DescriptorFormat.DisplayInBytes, bitmapManipulated.Height)); resultTextHeader += String.Format("extern {0}Pages;" + nl, heightVarName); } else { // in pixels resultTextSource += String.Format("{0}Pixels = {1};"+nl, heightVarName, bitmapManipulated.Height); resultTextHeader += String.Format("extern {0}Pixels;"+nl, heightVarName); } } }
// iterate through the original bitmaps and find the tightest common border private void findTightestCommonBitmapBorder(CharacterGenerationInfo[] charInfoArray, ref BitmapBorder tightestBorder) { // iterate through bitmaps for (int charIdx = 0; charIdx < charInfoArray.Length; ++charIdx) { // create a border BitmapBorder bitmapBorder = new BitmapBorder(); // get the bitmaps border getBitmapBorder(charInfoArray[charIdx].bitmapOriginal, bitmapBorder); // check if we need to loosen up the tightest border tightestBorder.leftX = Math.Min(bitmapBorder.leftX, tightestBorder.leftX); tightestBorder.topY = Math.Min(bitmapBorder.topY, tightestBorder.topY); tightestBorder.rightX = Math.Max(bitmapBorder.rightX, tightestBorder.rightX); tightestBorder.bottomY = Math.Max(bitmapBorder.bottomY, tightestBorder.bottomY); } }
// populate the font info private FontInfo populateFontInfo(Font font) { // the font information FontInfo fontInfo = new FontInfo(); // get teh characters we need to generate from the input text, removing duplicates fontInfo.generatedChars = getCharactersToGenerate(); // set font into into fontInfo.font = font; // array holding all bitmaps and info per character fontInfo.characters = new CharacterGenerationInfo[fontInfo.generatedChars.Length]; // // init char infos // for (int charIdx = 0; charIdx < fontInfo.generatedChars.Length; ++charIdx) { // create char info entity fontInfo.characters[charIdx] = new CharacterGenerationInfo(); // point back to teh font fontInfo.characters[charIdx].fontInfo = fontInfo; // set the character fontInfo.characters[charIdx].character = fontInfo.generatedChars[charIdx]; } // // Find the widest bitmap size we are going to draw // Rectangle largestBitmap = getLargestBitmapFromCharInfo(fontInfo.characters); // // create bitmaps per characater // // iterate over characters for (int charIdx = 0; charIdx < fontInfo.generatedChars.Length; ++charIdx) { // generate the original bitmap for the character convertCharacterToBitmap(fontInfo.generatedChars[charIdx], font, out fontInfo.characters[charIdx].bitmapOriginal, largestBitmap); // save // fontInfo.characters[charIdx].bitmapOriginal.Save(String.Format("C:/bms/{0}.bmp", fontInfo.characters[charIdx].character)); } // // iterate through all bitmaps and find the tightest common border. only perform // this if the configuration specifies // // this will contain the values of the tightest border around the characters BitmapBorder tightestCommonBorder = new BitmapBorder(); // only perform if padding type specifies if (m_outputConfig.paddingRemovalHorizontal == OutputConfiguration.PaddingRemoval.Fixed || m_outputConfig.paddingRemovalVertical == OutputConfiguration.PaddingRemoval.Fixed) { // find the common tightest border findTightestCommonBitmapBorder(fontInfo.characters, ref tightestCommonBorder); } // // iterate thruogh all bitmaps and generate the bitmap we will convert to string // this means performing all manipulation (pad remove, flip) // // iterate over characters for (int charIdx = 0; charIdx < fontInfo.generatedChars.Length; ++charIdx) { // generate the original bitmap for the character manipulateBitmap(fontInfo.characters[charIdx].bitmapOriginal, tightestCommonBorder, out fontInfo.characters[charIdx].bitmapToGenerate, m_outputConfig.spaceGenerationPixels, fontInfo.characters[charIdx].bitmapOriginal.Height); // for debugging // fontInfo.characters[charIdx].bitmapToGenerate.Save(String.Format("C:/bms/{0}_cropped.bmp", fontInfo.characters[charIdx].character)); } // // iterate through all characters and create the page array // // iterate over characters for (int charIdx = 0; charIdx < fontInfo.generatedChars.Length; ++charIdx) { // check if bitmap exists if (fontInfo.characters[charIdx].bitmapToGenerate != null) { // create the page array for the character convertBitmapToPageArray(fontInfo.characters[charIdx].bitmapToGenerate, out fontInfo.characters[charIdx].pages); } } // populate font info populateFontInfoFromCharacters(ref fontInfo); // return the font info return fontInfo; }
// generate the bitmap we will then use to convert to string (remove pad, flip) private bool manipulateBitmap(Bitmap bitmapOriginal, BitmapBorder tightestCommonBorder, out Bitmap bitmapManipulated, int minWidth, int minHeight) { // // First, crop // // get bitmap border - this sets teh crop rectangle to per bitmap, essentially BitmapBorder bitmapCropBorder = new BitmapBorder(); if (getBitmapBorder(bitmapOriginal, bitmapCropBorder) == false && minWidth == 0 && minHeight == 0) { // no data bitmapManipulated = null; // bitmap contains no data return false; } // check that width exceeds minimum if (bitmapCropBorder.rightX - bitmapCropBorder.leftX + 1 < 0) { // replace bitmapCropBorder.leftX = 0; bitmapCropBorder.rightX = minWidth - 1; } // check that height exceeds minimum if (bitmapCropBorder.bottomY - bitmapCropBorder.topY + 1 < 0) { // replace bitmapCropBorder.topY = 0; bitmapCropBorder.bottomY = minHeight - 1; } // should we crop hotizontally according to common if (m_outputConfig.paddingRemovalHorizontal == OutputConfiguration.PaddingRemoval.Fixed) { // cropped Y is according to common bitmapCropBorder.topY = tightestCommonBorder.topY; bitmapCropBorder.bottomY = tightestCommonBorder.bottomY; } // check if no horizontal crop is required else if (m_outputConfig.paddingRemovalHorizontal == OutputConfiguration.PaddingRemoval.None) { // set y to actual max border of bitmap bitmapCropBorder.topY = 0; bitmapCropBorder.bottomY = bitmapOriginal.Height - 1; } // should we crop vertically according to common if (m_outputConfig.paddingRemovalVertical == OutputConfiguration.PaddingRemoval.Fixed) { // cropped X is according to common bitmapCropBorder.leftX = tightestCommonBorder.leftX; bitmapCropBorder.rightX = tightestCommonBorder.rightX; } // check if no vertical crop is required else if (m_outputConfig.paddingRemovalVertical == OutputConfiguration.PaddingRemoval.None) { // set x to actual max border of bitmap bitmapCropBorder.leftX = 0; bitmapCropBorder.rightX = bitmapOriginal.Width - 1; } // now copy the output bitmap, cropped as required, to a temporary bitmap Rectangle rect = new Rectangle(bitmapCropBorder.leftX, bitmapCropBorder.topY, bitmapCropBorder.rightX - bitmapCropBorder.leftX + 1, bitmapCropBorder.bottomY - bitmapCropBorder.topY + 1); // clone the cropped bitmap into the generated one bitmapManipulated = bitmapOriginal.Clone(rect, bitmapOriginal.PixelFormat); // get rotate type RotateFlipType flipType = getOutputRotateFlipType(); // flip the cropped bitmap bitmapManipulated.RotateFlip(flipType); // bitmap contains data return true; }
// get the bitmaps border - that is where the black parts start private bool getBitmapBorder(Bitmap bitmap, BitmapBorder border) { // search for first column (x) from the left to contain data for (border.leftX = 0; border.leftX < bitmap.Width; ++border.leftX) { // if found first column from the left, stop looking if (!bitmapColumnIsEmpty(bitmap, border.leftX)) break; } // search for first column (x) from the right to contain data for (border.rightX = bitmap.Width - 1; border.rightX >= 0; --border.rightX) { // if found first column from the left, stop looking if (!bitmapColumnIsEmpty(bitmap, border.rightX)) break; } // search for first row (y) from the top to contain data for (border.topY = 0; border.topY < bitmap.Height; ++border.topY) { // if found first column from the left, stop looking if (!bitmapRowIsEmpty(bitmap, border.topY)) break; } // search for first row (y) from the bottom to contain data for (border.bottomY = bitmap.Height - 1; border.bottomY >= 0; --border.bottomY) { // if found first column from the left, stop looking if (!bitmapRowIsEmpty(bitmap, border.bottomY)) break; } // check if the bitmap contains any black pixels if (border.rightX == -1) { // no pixels were found return false; } else { // at least one black pixel was found return true; } }
// modify the original bitmap (adjust padding, flip, rotate, etc) private bool ManipulateBitmap(Bitmap bitmapOriginal, BitmapBorder tightestCommonBorder, out Bitmap bitmapManipulated, int minWidth, int minHeight, int interCharSpacing, RotateFlipType flipType) { // // First, crop // // get bitmap border - this sets the crop rectangle to per bitmap, essentially BitmapBorder bitmapCropBorder = new BitmapBorder(); if (this.GetBitmapBorder(bitmapOriginal, bitmapCropBorder, interCharSpacing) == false && minWidth == 0 && minHeight == 0) { // no data bitmapManipulated = null; // bitmap contains no data return false; } // check that width exceeds minimum if (bitmapCropBorder.rightX - bitmapCropBorder.leftX + 1 < minWidth) { // replace bitmapCropBorder.leftX = 0; bitmapCropBorder.rightX = minWidth - 1; } // check that height exceeds minimum if (bitmapCropBorder.bottomY - bitmapCropBorder.topY + 1 < minHeight) { // replace bitmapCropBorder.topY = 0; bitmapCropBorder.bottomY = minHeight - 1; } // crop horizontal bitmap switch (this.outputConfig.paddingRemovalHorizontal) { case OutputConfiguration.PaddingRemoval.None: // set X to original size minus one pixel bitmapCropBorder.leftX = 0; bitmapCropBorder.rightX = bitmapOriginal.Width - 1; break; case OutputConfiguration.PaddingRemoval.Fixed: // crop X to size of common border bitmapCropBorder.leftX = tightestCommonBorder.leftX; bitmapCropBorder.rightX = tightestCommonBorder.rightX; break; case OutputConfiguration.PaddingRemoval.Tightest: break; } // crop vertical bitmap switch (this.outputConfig.paddingRemovalVertical) { case OutputConfiguration.PaddingRemoval.None: // set Y to original size minus one pixel bitmapCropBorder.topY = 0; bitmapCropBorder.bottomY = bitmapOriginal.Height - 1; break; case OutputConfiguration.PaddingRemoval.Fixed: // crop Y to size of common border bitmapCropBorder.topY = tightestCommonBorder.topY; bitmapCropBorder.bottomY = tightestCommonBorder.bottomY; break; case OutputConfiguration.PaddingRemoval.Tightest: // crop Y to size of common border bitmapCropBorder.topY = tightestCommonBorder.topY; bitmapCropBorder.bottomY = tightestCommonBorder.bottomY; break; } // now create the crop rectangle Rectangle cropRect = new Rectangle(bitmapCropBorder.leftX, bitmapCropBorder.topY, bitmapCropBorder.rightX - bitmapCropBorder.leftX + 1, bitmapCropBorder.bottomY - bitmapCropBorder.topY + 1); // clone the cropped bitmap into the generated one bitmapManipulated = bitmapOriginal.Clone(cropRect, bitmapOriginal.PixelFormat); // flip the cropped bitmap bitmapManipulated.RotateFlip(flipType); // bitmap contains data return true; }
// get the bitmaps border - that is where the black parts start private bool GetBitmapBorder(Bitmap bitmap, BitmapBorder border, int interCharSpacing) { // search for first column (x) from the left to contain data for (border.leftX = 0; border.leftX < bitmap.Width; border.leftX++) { // if set pixels found, stop looking if (this.BitmapColumnIsEmpty(bitmap, border.leftX) == false) { break; } } // search for first column (x) from the right to contain data for (border.rightX = bitmap.Width - 1; border.rightX >= 0; border.rightX--) { // if set pixels found, stop looking if (this.BitmapColumnIsEmpty(bitmap, border.rightX) == false) { break; } } // set top border at 0 border.topY = 0; // search for first row (y) from the bottom to contain data for (border.bottomY = bitmap.Height - 1; border.bottomY >= 0; border.bottomY--) { // if set pixels found, stop looking if (this.BitmapRowIsEmpty(bitmap, border.bottomY) == false) { break; } } // check if the bitmap contains any black pixels if (border.rightX == -1) { // no pixels were found return false; } // add inter-character spacing border.rightX += interCharSpacing; return true; }
private FontInfo CreateFontInfo(Font font) { // the font information FontInfo fontInfo = new FontInfo(); // set name and size fontInfo.FontName = font.Name.Replace(" ", "") + Math.Round(font.Size); fontInfo.FontSize = (int)Math.Round(font.Size); // get the characters we need to generate from the input text, removing duplicates fontInfo.GeneratedChars = this.GetCharactersToGenerate(); // save reference to the font fontInfo.WindowsFont = font; // create array to hold all bitmaps and info per character fontInfo.Characters = new CharacterGenerationInfo[fontInfo.GeneratedChars.Length]; // // init character info // for (int charIndex = 0; charIndex < fontInfo.GeneratedChars.Length; charIndex++) { // create char info entity fontInfo.Characters[charIndex] = new CharacterGenerationInfo(fontInfo, fontInfo.GeneratedChars[charIndex]); } // // find the largest bitmap size we are going to draw // Rectangle largestBitmapSize = this.GetSizeOfLargestBitmap(fontInfo.Characters, this.outputConfig.interCharacterPixels); // update font height fontInfo.CharHeight = (ushort)largestBitmapSize.Height; // // create bitmaps per character // // iterate over characters for (int charIndex = 0; charIndex < fontInfo.GeneratedChars.Length; charIndex++) { // generate the original bitmap for the character this.ConvertCharacterToBitmap(fontInfo.GeneratedChars[charIndex], font, out fontInfo.Characters[charIndex].BitmapOriginal, largestBitmapSize); // save // fontInfo.characters[charIndex].bitmapOriginal.Save(String.Format("C:/bms/{0}.bmp", fontInfo.characters[charIndex].character)); } // // iterate through all bitmaps and find the tightest common border // // this will contain the values of the tightest border around the characters BitmapBorder tightestCommonBorder = new BitmapBorder(); this.FindTightestCommonBitmapBorder(fontInfo.Characters, tightestCommonBorder); // // iterate thruogh all bitmaps and generate the bitmap we will use as output // this means performing all manipulation (pad remove, flip) // // iterate over characters for (int charIndex = 0; charIndex < fontInfo.GeneratedChars.Length; charIndex++) { // generate output bitmap for the character this.ManipulateBitmap(fontInfo.Characters[charIndex].BitmapOriginal, tightestCommonBorder, out fontInfo.Characters[charIndex].BitmapToGenerate, (fontInfo.Characters[charIndex].Character == ' ' ? this.outputConfig.spaceCharacterWidth : this.outputConfig.minCharacterWidth), this.outputConfig.minCharacterHeight, this.outputConfig.interCharacterPixels, this.GetOutputRotateFlipType()); } // // iterate through all characters and create the char array // // iterate over characters for (int charIndex = 0; charIndex < fontInfo.GeneratedChars.Length; charIndex++) { // check if bitmap exists if (fontInfo.Characters[charIndex].BitmapToGenerate != null) { // create a ushort array from the character's bitmap this.ConvertBitmapToUshortArray(fontInfo.Characters[charIndex].BitmapToGenerate, fontInfo.Characters[charIndex].BitmapArray); // trim blank pixels from bottom of bitmap int bitmapLength = fontInfo.Characters[charIndex].BitmapArray.Count; while (bitmapLength > 1 && fontInfo.Characters[charIndex].BitmapArray[bitmapLength - 1] == 0x8000) { fontInfo.Characters[charIndex].BitmapArray.RemoveAt(bitmapLength - 1); bitmapLength = fontInfo.Characters[charIndex].BitmapArray.Count; } // save the character's bitmap length fontInfo.Characters[charIndex].BitmapLength = (ushort)fontInfo.Characters[charIndex].BitmapArray.Count; } } // update font info this.UpdateFontInfoFromCharacters(fontInfo); // return the font info return fontInfo; }
// modify the original bitmap (adjust padding, flip, rotate, etc) private bool ManipulateBitmap(Bitmap bitmapOriginal, BitmapBorder tightestCommonBorder, out Bitmap bitmapManipulated, int minWidth, int minHeight, int interCharSpacing, RotateFlipType flipType) { // // First, crop // // get bitmap border - this sets the crop rectangle to per bitmap, essentially BitmapBorder bitmapCropBorder = new BitmapBorder(); if (this.GetBitmapBorder(bitmapOriginal, bitmapCropBorder, interCharSpacing) == false && minWidth == 0 && minHeight == 0) { // no data bitmapManipulated = null; // bitmap contains no data return(false); } // check that width exceeds minimum if (bitmapCropBorder.rightX - bitmapCropBorder.leftX + 1 < minWidth) { // replace bitmapCropBorder.leftX = 0; bitmapCropBorder.rightX = minWidth - 1; } // check that height exceeds minimum if (bitmapCropBorder.bottomY - bitmapCropBorder.topY + 1 < minHeight) { // replace bitmapCropBorder.topY = 0; bitmapCropBorder.bottomY = minHeight - 1; } // crop horizontal bitmap switch (this.outputConfig.paddingRemovalHorizontal) { case OutputConfiguration.PaddingRemoval.None: // set X to original size minus one pixel bitmapCropBorder.leftX = 0; bitmapCropBorder.rightX = bitmapOriginal.Width - 1; break; case OutputConfiguration.PaddingRemoval.Fixed: // crop X to size of common border bitmapCropBorder.leftX = tightestCommonBorder.leftX; bitmapCropBorder.rightX = tightestCommonBorder.rightX; break; case OutputConfiguration.PaddingRemoval.Tightest: break; } // crop vertical bitmap switch (this.outputConfig.paddingRemovalVertical) { case OutputConfiguration.PaddingRemoval.None: // set Y to original size minus one pixel bitmapCropBorder.topY = 0; bitmapCropBorder.bottomY = bitmapOriginal.Height - 1; break; case OutputConfiguration.PaddingRemoval.Fixed: // crop Y to size of common border bitmapCropBorder.topY = tightestCommonBorder.topY; bitmapCropBorder.bottomY = tightestCommonBorder.bottomY; break; case OutputConfiguration.PaddingRemoval.Tightest: // crop Y to size of common border bitmapCropBorder.topY = tightestCommonBorder.topY; bitmapCropBorder.bottomY = tightestCommonBorder.bottomY; break; } // now create the crop rectangle Rectangle cropRect = new Rectangle(bitmapCropBorder.leftX, bitmapCropBorder.topY, bitmapCropBorder.rightX - bitmapCropBorder.leftX + 1, bitmapCropBorder.bottomY - bitmapCropBorder.topY + 1); // clone the cropped bitmap into the generated one bitmapManipulated = bitmapOriginal.Clone(cropRect, bitmapOriginal.PixelFormat); // flip the cropped bitmap bitmapManipulated.RotateFlip(flipType); // bitmap contains data return(true); }
private FontInfo CreateFontInfo(Font font) { // the font information FontInfo fontInfo = new FontInfo(); // set name and size fontInfo.FontName = font.Name.Replace(" ", "") + Math.Round(font.Size); fontInfo.FontSize = (int)Math.Round(font.Size); // get the characters we need to generate from the input text, removing duplicates fontInfo.GeneratedChars = this.GetCharactersToGenerate(); // save reference to the font fontInfo.WindowsFont = font; // create array to hold all bitmaps and info per character fontInfo.Characters = new CharacterGenerationInfo[fontInfo.GeneratedChars.Length]; // // init character info // for (int charIndex = 0; charIndex < fontInfo.GeneratedChars.Length; charIndex++) { // create char info entity fontInfo.Characters[charIndex] = new CharacterGenerationInfo(fontInfo, fontInfo.GeneratedChars[charIndex]); } // // find the largest bitmap size we are going to draw // Rectangle largestBitmapSize = this.GetSizeOfLargestBitmap(fontInfo.Characters, this.outputConfig.interCharacterPixels); // update font height fontInfo.CharHeight = (ushort)largestBitmapSize.Height; // // create bitmaps per character // // iterate over characters for (int charIndex = 0; charIndex < fontInfo.GeneratedChars.Length; charIndex++) { // generate the original bitmap for the character this.ConvertCharacterToBitmap(fontInfo.GeneratedChars[charIndex], font, out fontInfo.Characters[charIndex].BitmapOriginal, largestBitmapSize); // save // fontInfo.characters[charIndex].bitmapOriginal.Save(String.Format("C:/bms/{0}.bmp", fontInfo.characters[charIndex].character)); } // // iterate through all bitmaps and find the tightest common border // // this will contain the values of the tightest border around the characters BitmapBorder tightestCommonBorder = new BitmapBorder(); this.FindTightestCommonBitmapBorder(fontInfo.Characters, tightestCommonBorder); // // iterate thruogh all bitmaps and generate the bitmap we will use as output // this means performing all manipulation (pad remove, flip) // // iterate over characters for (int charIndex = 0; charIndex < fontInfo.GeneratedChars.Length; charIndex++) { // generate output bitmap for the character this.ManipulateBitmap(fontInfo.Characters[charIndex].BitmapOriginal, tightestCommonBorder, out fontInfo.Characters[charIndex].BitmapToGenerate, (fontInfo.Characters[charIndex].Character == ' ' ? this.outputConfig.spaceCharacterWidth : this.outputConfig.minCharacterWidth), this.outputConfig.minCharacterHeight, this.outputConfig.interCharacterPixels, this.GetOutputRotateFlipType()); } // // iterate through all characters and create the char array // // iterate over characters for (int charIndex = 0; charIndex < fontInfo.GeneratedChars.Length; charIndex++) { // check if bitmap exists if (fontInfo.Characters[charIndex].BitmapToGenerate != null) { // create a ushort array from the character's bitmap this.ConvertBitmapToUshortArray(fontInfo.Characters[charIndex].BitmapToGenerate, fontInfo.Characters[charIndex].BitmapArray); // trim blank pixels from bottom of bitmap int bitmapLength = fontInfo.Characters[charIndex].BitmapArray.Count; while (bitmapLength > 1 && fontInfo.Characters[charIndex].BitmapArray[bitmapLength - 1] == 0x8000) { fontInfo.Characters[charIndex].BitmapArray.RemoveAt(bitmapLength - 1); bitmapLength = fontInfo.Characters[charIndex].BitmapArray.Count; } // save the character's bitmap length fontInfo.Characters[charIndex].BitmapLength = (ushort)fontInfo.Characters[charIndex].BitmapArray.Count; } } // update font info this.UpdateFontInfoFromCharacters(fontInfo); // return the font info return(fontInfo); }