using System; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Text; using System.IO; using System.Linq; using System.Runtime.InteropServices; using TSpdf.Kernel.Font; using TSpdf.IO.Font.Constants; using static tsPDFUtilsCore.Imagenes; using static tsPDFUtilsCore.Enums; namespace tsPDFUtilsCore { public class Imagenes { public static Bitmap RedimensionaImagen(Bitmap Original, int NuevoAlto, int NuevoAncho, int CoordenadaX, int CoordenadaY) { Bitmap newImage = new Bitmap(NuevoAncho, NuevoAlto); using (Graphics g = Graphics.FromImage(newImage)) { g.Clear(Color.Transparent); g.DrawImage(Original, CoordenadaX, CoordenadaY, Original.Width, Original.Height); } return newImage; } public static Bitmap crearBitMapFirmas(List listadoTextos, List listadoImagenes, List ListadoFuentes, TSpdf.Kernel.Geom.Rectangle medidas) { int dpi = 600; int anchoPixeles = (int)medidas.GetWidth() * dpi / 72; int altoPixeles = (int)medidas.GetHeight() * dpi / 72; Bitmap bmp = new Bitmap(anchoPixeles, altoPixeles, PixelFormat.Format32bppArgb); bmp.SetResolution(dpi, dpi); Graphics g = Graphics.FromImage(bmp); g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; g.Clear(Color.Transparent); // Dibujar textos foreach (var texto in listadoTextos) { Font font = null; if (FontFamily.Families.Any(x => x.Name == texto.NombreFuente)) font = new Font(FontFamily.Families.Where(x => x.Name == texto.NombreFuente).First(), texto.size, texto.estiloTexto, GraphicsUnit.Point); else if (ListadoFuentes != null && ListadoFuentes.Any(x => x.NombreFuente == texto.NombreFuente)) { var fuente = ListadoFuentes.Where(x => x.NombreFuente == texto.NombreFuente).First(); int dataLength = fuente.memoryFont.Length; IntPtr ptrData = Marshal.AllocCoTaskMem(dataLength); Marshal.Copy(fuente.memoryFont, 0, ptrData, dataLength); PrivateFontCollection privateFontCollection = new PrivateFontCollection(); privateFontCollection.AddMemoryFont(ptrData, dataLength); font = new Font(privateFontCollection.Families.FirstOrDefault(), texto.size, texto.estiloTexto, GraphicsUnit.Point); } else throw new Exception("Fuente " + texto.NombreFuente + " no encontrada"); var sizeTexto = g.MeasureString(texto.texto, font); var coordenadaX = calcularX(texto.distanciaX, texto.distanciaY, texto.PosicionEsquina, bmp, texto.anguloRotacion, (int)sizeTexto.Width, (int)sizeTexto.Height); var coordenadaY = calcularY(texto.distanciaY, texto.distanciaX, texto.PosicionEsquina, bmp, texto.anguloRotacion, (int)sizeTexto.Width, (int)sizeTexto.Height); PointF rotationPoint = new PointF(texto.distanciaX, texto.distanciaY); g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; StringFormat stringFormat = new StringFormat(); g.TranslateTransform(0, 0); g.RotateTransform(texto.anguloRotacion); if (texto.AlineacionTexto != AlineamientoEnum.JUSTIFICADO) g.DrawString(texto.texto, font, texto.colorTexto, new PointF(coordenadaX, coordenadaY)); else DrawJustifiedString(ref g, texto.texto, font, texto.colorTexto, new RectangleF(coordenadaX, coordenadaY, altoPixeles, sizeTexto.Height), stringFormat); g.ResetTransform(); } foreach (var imagen in listadoImagenes) { MemoryStream stream = new MemoryStream(); stream.Write(imagen.Imagen, 0, imagen.Imagen.Length); System.Drawing.Image myImage = System.Drawing.Image.FromStream(stream); g.TranslateTransform(0, 0); g.RotateTransform(imagen.AnguloRotacion); int coordenadaX = calcularX(imagen.PosicionX, imagen.PosicionY, imagen.PosicionEsquina, bmp, imagen.AnguloRotacion, myImage.Width, myImage.Height); int coordenadaY = calcularY(imagen.PosicionY, imagen.PosicionX, imagen.PosicionEsquina, bmp, imagen.AnguloRotacion, myImage.Width, myImage.Height); if (altoPixeles > anchoPixeles) g.DrawImage(myImage, new Rectangle(coordenadaX, coordenadaY, altoPixeles, anchoPixeles)); else g.DrawImage(myImage, new Rectangle(coordenadaX, coordenadaY, anchoPixeles, altoPixeles)); g.ResetTransform(); } return bmp; } public static byte[] BitMapAByteArray(Bitmap bmp) { MemoryStream msSalida = new MemoryStream(); bmp.Save(msSalida, ImageFormat.Png); byte[] byteArray = msSalida.ToArray(); msSalida.Close(); return byteArray; } public static void DrawJustifiedString(ref Graphics g, string txt, Font font, Brush brush, RectangleF destination, StringFormat format) { using (StringFormat fmt = (StringFormat)format.Clone()) { fmt.FormatFlags = fmt.FormatFlags | StringFormatFlags.MeasureTrailingSpaces; CharacterRange[] cr = { new CharacterRange(0, 1) }; fmt.SetMeasurableCharacterRanges(cr); fmt.Alignment = StringAlignment.Center; float txtWidth = g.MeasureString(txt, font, destination.Location, fmt).Width; float spacing = (destination.Width - txtWidth) / (txt.Length - 1); RectangleF dest = new RectangleF(destination.X, destination.Y, 0, destination.Height); foreach (char c in txt.AsEnumerable()) { // Graphics#MeasureString is too inaccurate for character placement dest.Width = g.MeasureCharacterRanges(c.ToString(), font, destination, fmt)[0].GetBounds(g).Width; g.DrawString(c.ToString(), font, brush, dest, fmt); dest.X += dest.Width + spacing; } } } private static int calcularX(int coordenadaX, int coordenadaY, EsquinaEnum PosicionEsquina, Bitmap medidasFirma, float rotacionElemento, int anchoElemento, int altoElemento) { int anchoFirma = medidasFirma.Width; int altoFirma = medidasFirma.Height; int ejeX = 0; switch (PosicionEsquina) { case EsquinaEnum.SUPERIOR_IZQUIERDA: { switch (rotacionElemento) { case 90: { ejeX = coordenadaY; break; } case 180: { ejeX = -coordenadaX - anchoElemento; break; } case 270: { ejeX = -coordenadaY - anchoElemento; break; } default: { ejeX = coordenadaX; break; } } break; } case EsquinaEnum.INFERIOR_IZQUIERDA: { switch (rotacionElemento) { case 90: { ejeX = (altoFirma - (coordenadaY + anchoElemento)); break; } case 180: { ejeX = -coordenadaX - anchoElemento; break; } case 270: { ejeX = coordenadaY - altoFirma; break; } default: { ejeX = coordenadaX; break; } } break; } case EsquinaEnum.SUPERIOR_DERECHA: { switch (rotacionElemento) { case 90: { ejeX = coordenadaY; break; } case 180: { ejeX = -anchoFirma + coordenadaX; break; } case 270: { ejeX = -coordenadaY - anchoElemento; break; } default: { ejeX = anchoFirma - (anchoElemento + coordenadaX); break; } } break; } case EsquinaEnum.INFERIOR_DERECHA: { switch (rotacionElemento) { case 90: { ejeX = (altoFirma - (coordenadaY + anchoElemento)); break; } case 180: { ejeX = -anchoFirma + coordenadaX; break; } case 270: { ejeX = coordenadaY - altoFirma; break; } default: { ejeX = anchoFirma - (anchoElemento + coordenadaX); break; } } break; } } return ejeX; } private static int calcularY(int coordenadaY, int coordenadaX, EsquinaEnum PosicionEsquina, Bitmap medidasFirma, float rotacionElemento, int anchoElemento, int altoElemento) { int anchoFirma = medidasFirma.Width; int altoFirma = medidasFirma.Height; int ejeY = 0; switch (PosicionEsquina) { case EsquinaEnum.SUPERIOR_IZQUIERDA: { switch (rotacionElemento) { case 90: { ejeY = -coordenadaX - altoElemento; break; } case 180: { ejeY = -coordenadaY - altoElemento; break; } case 270: { ejeY = coordenadaX; break; } default: { ejeY = coordenadaY; break; } } break; } case EsquinaEnum.INFERIOR_IZQUIERDA: { switch (rotacionElemento) { case 90: { ejeY = -coordenadaX - altoElemento; break; } case 180: { ejeY = -altoFirma + coordenadaY; break; } case 270: { ejeY = coordenadaX; break; } default: { ejeY = altoFirma - (altoElemento + coordenadaY); break; } } break; } case EsquinaEnum.SUPERIOR_DERECHA: { switch (rotacionElemento) { case 90: { ejeY = coordenadaX - (anchoFirma); break; } case 180: { ejeY = -coordenadaY - altoElemento; break; } case 270: { ejeY = anchoFirma - (altoElemento + coordenadaX); break; } default: { ejeY = coordenadaY; break; } } break; } case EsquinaEnum.INFERIOR_DERECHA: { switch (rotacionElemento) { case 90: { ejeY = coordenadaX - (anchoFirma); break; } case 180: { ejeY = -altoFirma + coordenadaY; break; } case 270: { ejeY = anchoFirma - (altoElemento + coordenadaX); break; } default: { ejeY = altoFirma - (altoElemento + coordenadaY); break; } } break; } } return ejeY; } private static TSpdf.Kernel.Font.PdfFont devolverTipoFuente(string nombreFuente) { TSpdf.Kernel.Font.PdfFont tipoFuente; switch (nombreFuente) { case "COURIER": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER); break; } case "COURIER_BOLD": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER_BOLD); break; } case "COURIER_BOLDOBLIQUE": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER_BOLDOBLIQUE); break; } case "COURIER_OBLIQUE": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.COURIER_OBLIQUE); break; } case "HELVETICA": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA); break; } case "HELVETICA_BOLD": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLD); break; } case "HELVETICA_BOLDOBLIQUE": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_BOLDOBLIQUE); break; } case "HELVETICA_OBLIQUE": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.HELVETICA_OBLIQUE); break; } case "SYMBOL": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.SYMBOL); break; } case "TIMES_ROMAN": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN); break; } case "TIMES_BOLD": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_BOLD); break; } case "TIMES_BOLDITALIC": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_BOLDITALIC); break; } case "TIMES_ITALIC": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_ITALIC); break; } case "ZAPFDINGBATS": { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.ZAPFDINGBATS); break; } default: { tipoFuente = PdfFontFactory.CreateFont(StandardFonts.TIMES_ROMAN); break; } } return tipoFuente; } } } public enum EsquinaEnum : int { INFERIOR_IZQUIERDA = 0, INFERIOR_DERECHA = 1, SUPERIOR_IZQUIERDA = 2, SUPERIOR_DERECHA = 3 } public enum AlineamientoEnum : int { IZQUIERDA = 0, DERECHA = 1, CENTRO = 2, JUSTIFICADO = 3, JUSTIFICADO_ALL = 4 } public enum TipoTextoEnum : int { NORMAL = 0, NUMERO_PAGINA = 1, NUMERO_PAGINA_TOTAL_PAGINAS = 2, } public enum FuenteEnum { COURIER, COURIER_BOLD, COURIER_BOLDOBLIQUE, COURIER_OBLIQUE, HELVETICA, HELVETICA_BOLD, HELVETICA_BOLDOBLIQUE, HELVETICA_OBLIQUE, SYMBOL, TIMES_ROMAN, TIMES_BOLD, TIMES_BOLDITALIC, TIMES_ITALIC, ZAPFDINGBATS }