Exemple #1
0
        static int borderThickness = 1;   // It's just 1. Won't really change, but whatever. If you change it, things will get fucky.

        public static bool MakePDF(Ragecomic comic, string pdffile)
        {
            using (System.IO.FileStream fs = new FileStream(pdffile, FileMode.Create))
            {
                int rows   = (int)Math.Ceiling((double)comic.panels / 2);
                int width  = rowWidth * 2 + borderThickness * 3;
                int height = rowHeight * rows + borderThickness * rows + borderThickness; // 239 per row, plus 1 pixel border per row, plus 1 pixel extra border

                ZipFile drawImageZip  = new ZipFile();
                bool    hasDrawImages = comic.items.getDrawImageCount() > 0;

                if (hasDrawImages)
                {
                    drawImageZip.Dispose();
                    string addition = "";
                    int    nr       = 1;
                    while (File.Exists(pdffile + ".drawimages" + addition + ".zip"))
                    {
                        addition = "_" + (nr++).ToString();
                    }
                    drawImageZip = new ZipFile(pdffile + ".drawimages" + addition + ".zip");
                }


                // Create an instance of the document class which represents the PDF document itself.
                Rectangle pageSize = new Rectangle(width, height);
                Document  document = new Document(pageSize, 0, 0, 0, 0);
                // Create an instance to the PDF file by creating an instance of the PDF
                // Writer class using the document and the filestrem in the constructor.

                PdfWriter writer = PdfWriter.GetInstance(document, fs);

                document.AddAuthor("Derp");

                document.AddCreator("RagemakerToPDF");

                document.AddKeywords("rage, comic");

                document.AddSubject("A rage comic");

                document.AddTitle("A rage comic");
                // Open the document to enable you to write to the document

                document.Open();


                PdfContentByte cb = writer.DirectContent;

                // Fill background with white
                Rectangle rect = new iTextSharp.text.Rectangle(0, 0, width, height);
                rect.BackgroundColor = new BaseColor(255, 255, 255);
                cb.Rectangle(rect);

                // Draw grid on bottom if it isn't set to be on top.
                if (!comic.gridAboveAll && comic.showGrid)
                {
                    DrawGrid(cb, width, height, rows, comic);
                }

                //List<MyMedia.FontFamily> families =  MyMedia.Fonts.SystemFontFamilies.ToList();

                // This was a neat idea, but it's much too slow
                //List<string> files = FontFinder.GetFilesForFont("Courier New").ToList();

                //string filename = FontFinder.GetSystemFontFileName(families[0].)

                //Draw.Font testFont = new Draw.Font(new Draw.FontFamily("Courier New"),12f,Draw.FontStyle.Regular  | Draw.FontStyle.Bold);

                string courierPath     = FontFinder.GetSystemFontFileName("Courier New", true);
                string courierBoldPath = FontFinder.GetSystemFontFileName("Courier New", true, Draw.FontStyle.Bold);
                string tahomaPath      = FontFinder.GetSystemFontFileName("Tahoma", true, Draw.FontStyle.Bold);

                // Define base fonts
                Font[] fonts = new Font[3];
                fonts[0] = new Font(BaseFont.CreateFont(courierPath, BaseFont.CP1252, BaseFont.EMBEDDED));
                fonts[1] = new Font(BaseFont.CreateFont(courierBoldPath, BaseFont.CP1252, BaseFont.EMBEDDED));
                fonts[2] = new Font(BaseFont.CreateFont(tahomaPath, BaseFont.CP1252, BaseFont.EMBEDDED));

                /*fonts[0] = BaseFont.CreateFont("fonts/TRCourierNew.ttf", BaseFont.CP1252, BaseFont.EMBEDDED);
                 * fonts[1] = BaseFont.CreateFont("fonts/TRCourierNewBold.ttf", BaseFont.CP1252, BaseFont.EMBEDDED);
                 * fonts[2] = new Font(BaseFont.CreateFont("fonts/Tahoma-Bold.ttf", BaseFont.CP1252, BaseFont.EMBEDDED));*/

                int drawimageindex = 0;

                int index = 0;
                foreach (var item in comic.items)
                {
                    if (item is Face)
                    {
                        Face  face = (Face)item;
                        Image pdfImage;
                        System.Drawing.Image faceImage;
                        // If mirroring is necessary, we have to read the image via C# and use RotateFlip, as iTextSharp doesn't support mirroring.
                        if (face.mirrored)
                        {
                            // If it's a JPEG, open it with Flux.JPEG.Core, because the internal JPEG decoder (and also LibJpeg.NET) creates weird dithering artifacts with greyscale JPGs, which some of the rage faces are.
                            if (Path.GetExtension(face.file).ToLower() == ".jpeg" || Path.GetExtension(face.file).ToLower() == ".jpg")
                            {
                                FileStream jpegstream            = File.OpenRead("images/" + face.file);
                                FluxJpeg.Core.DecodedJpeg myJpeg = new JpegDecoder(jpegstream).Decode();

                                // Only use this JPEG decoder if the colorspace is Gray. Otherwise the normal one is just fine.
                                if (myJpeg.Image.ColorModel.colorspace == FluxJpeg.Core.ColorSpace.Gray)
                                {
                                    myJpeg.Image.ChangeColorSpace(FluxJpeg.Core.ColorSpace.YCbCr);
                                    faceImage = myJpeg.Image.ToBitmap();
                                }
                                else
                                {
                                    faceImage = System.Drawing.Image.FromFile("images/" + face.file);
                                }
                            }
                            else
                            {
                                faceImage = System.Drawing.Image.FromFile("images/" + face.file);
                            }

                            // Apply mirroring
                            faceImage.RotateFlip(System.Drawing.RotateFlipType.RotateNoneFlipX);
                            pdfImage = Image.GetInstance(faceImage, System.Drawing.Imaging.ImageFormat.Png);
                        }
                        else
                        {
                            // Just let iTextSharp handle it if no mirroring is required. Will also save space (presumably)
                            pdfImage = Image.GetInstance("images/" + face.file);
                        }

                        pdfImage.ScalePercent(face.scalex * 100, face.scaley * 100);
                        pdfImage.Rotation = -(float)Math.PI * face.rotation / 180.0f;
                        pdfImage.SetAbsolutePosition(item.x, (height - item.y) - pdfImage.ScaledHeight);

                        // Set opacity to proper value
                        if (face.opacity < 1)
                        {
                            PdfGState graphicsState = new PdfGState();
                            graphicsState.FillOpacity = face.opacity;
                            cb.SetGState(graphicsState);
                        }

                        cb.AddImage(pdfImage);

                        // Set back to normal
                        if (face.opacity < 1)
                        {
                            PdfGState graphicsState = new PdfGState();
                            graphicsState.FillOpacity = 1f;
                            cb.SetGState(graphicsState);
                        }
                    }

                    else if (item is DrawImage)
                    {
                        DrawImage drawimage = (DrawImage)item;

                        drawImageZip.AddEntry("drawimage_" + (drawimageindex++).ToString() + ".png", drawimage.imagedata);

                        System.Drawing.Image pngImage = System.Drawing.Image.FromStream(new MemoryStream(drawimage.imagedata));
                        Image pdfImage = Image.GetInstance(pngImage, System.Drawing.Imaging.ImageFormat.Png);

                        // Rotation is NOT to be applied. Ragemaker actually has a bug that causes it to save rotated images in their rotated form, but save the rotation value anyway
                        // Thus rotating the image by the rotation value will actually rotate them double compared to what they originally looked like
                        // The irony is that ragemaker *itself* cannot properly load an xml it created with this rotation value, as it will also apply the rotation
                        // As such, this tool is currently the only way to correctly display that .xml file as it was originally meant to look, not even ragemaker itself can properly load it again.
                        //pdfImage.Rotation = -(float)Math.PI * item.rotation / 180.0f;

                        pdfImage.SetAbsolutePosition(item.x, (height - item.y) - pdfImage.ScaledHeight);

                        // Opacity likewise seems to be baked in, and in fact the opacity value doesn't even exist.
                        // Implementing it anyway, in case it ever becomes a thing.
                        if (drawimage.opacity < 1)
                        {
                            PdfGState graphicsState = new PdfGState();
                            graphicsState.FillOpacity = drawimage.opacity;
                            cb.SetGState(graphicsState);
                        }
                        cb.AddImage(pdfImage);

                        // Set back to normal
                        if (drawimage.opacity < 1)
                        {
                            PdfGState graphicsState = new PdfGState();
                            graphicsState.FillOpacity = 1f;
                            cb.SetGState(graphicsState);
                        }
                    }


                    else if (item is Text)
                    {
                        int  padding = 4;
                        Text text    = (Text)item;

                        // Create template
                        PdfTemplate xobject = cb.CreateTemplate(text.width, text.height);

                        // Background color (if set)
                        if (text.bgOn)
                        {
                            Rectangle            bgRectangle = new Rectangle(0, 0, text.width, text.height);
                            System.Drawing.Color bgColor     = System.Drawing.ColorTranslator.FromHtml(text.bgColor);
                            rect.BackgroundColor = new BaseColor(bgColor.R, bgColor.G, bgColor.B, (int)Math.Floor(text.opacity * 255));

                            xobject.Rectangle(rect);
                        }

                        // Create text
                        Rectangle  textangle = new Rectangle(padding, 0, text.width - padding, text.height);
                        ColumnText ct        = new ColumnText(xobject);
                        ct.SetSimpleColumn(textangle);
                        Paragraph paragraph = new Paragraph(text.text);

                        Font myFont = fonts[text.style];



                        // More specific treatment if it's an AnyFont element which allows the user to select any font and styles, not just the normal 3 presets
                        // This isn't perfect, as the current FontFinder doesn't indicate whether he actually found an Italic/Bold typeface, hence it's not possible
                        // to determine whether faux-italic/faux-bold should be applied. Currently it will only work correctly if each used font has a specific typeface
                        // for the needed styles (bold or italic), otherwise incorrect results.
                        // TODO Fix, for example let FontFinder return array of strings, one of which is indicating the suffix that was found.
                        if (text is AnyFontText)
                        {
                            AnyFontText anyfont  = (AnyFontText)text;
                            string      fontname = anyfont.font;
                            string      fontfile = "";
                            if (anyfont.bold)
                            {
                                fontfile = FontFinder.GetSystemFontFileName(fontname, true, Draw.FontStyle.Bold);
                                int fontStyle = 0;
                                if (anyfont.italic)
                                {
                                    fontStyle |= Font.ITALIC;
                                }
                                if (anyfont.underline)
                                {
                                    fontStyle |= Font.UNDERLINE;
                                }
                                myFont = new Font(BaseFont.CreateFont(fontfile, BaseFont.CP1252, BaseFont.EMBEDDED), 100f, fontStyle);
                            }
                            else if (anyfont.italic)
                            {
                                fontfile = FontFinder.GetSystemFontFileName(fontname, true, Draw.FontStyle.Italic);
                                int fontStyle = 0;
                                if (anyfont.underline)
                                {
                                    fontStyle |= Font.UNDERLINE;
                                }
                                myFont = new Font(BaseFont.CreateFont(fontfile, BaseFont.CP1252, BaseFont.EMBEDDED), 100f, fontStyle);
                            }
                            else
                            {
                                fontfile = FontFinder.GetSystemFontFileName(fontname, true, Draw.FontStyle.Regular);
                                int fontStyle = 0;
                                if (anyfont.underline)
                                {
                                    fontStyle |= Font.UNDERLINE;
                                }
                                myFont = new Font(BaseFont.CreateFont(fontfile, BaseFont.CP1252, BaseFont.EMBEDDED), 100f, fontStyle);
                            }
                        }



                        myFont.Size = text.size;
                        System.Drawing.Color color = (System.Drawing.Color)(new System.Drawing.ColorConverter()).ConvertFromString(text.color);
                        myFont.Color        = new BaseColor(color.R, color.G, color.B, (int)Math.Floor(text.opacity * 255));
                        paragraph.Font      = myFont;
                        paragraph.Alignment = text.align == Text.ALIGN.LEFT ? PdfContentByte.ALIGN_LEFT : (text.align == Text.ALIGN.RIGHT ? PdfContentByte.ALIGN_RIGHT : PdfContentByte.ALIGN_CENTER);
                        paragraph.SetLeading(0, 1.12f);
                        ct.AddElement(paragraph);
                        ct.Go();


                        // Angle to radians
                        float angle = (float)Math.PI * text.rotation / 180.0f;

                        // Calculate Bounding Box size for correct placement later
                        GraphicsPath gp = new GraphicsPath();
                        gp.AddRectangle(new System.Drawing.Rectangle(0, 0, (int)Math.Round(text.width), (int)Math.Round(text.height)));
                        Matrix translateMatrix = new Matrix();
                        translateMatrix.RotateAt(text.rotation, new System.Drawing.PointF(text.width / 2, text.height / 2));
                        gp.Transform(translateMatrix);
                        var   gbp = gp.GetBounds();
                        float newWidth = gbp.Width, newHeight = gbp.Height;

                        // Create correct placement
                        // Background info: I rotate around the center of the text box, thus the center of the text box is what I attempt to place correctly with the initial .Translate()
                        AffineTransform transform = new AffineTransform();
                        transform.Translate(item.x + newWidth / 2 - text.width / 2, height - (item.y + newHeight / 2 - text.height / 2) - text.height);
                        transform.Rotate(-angle, text.width / 2, text.height / 2);

                        cb.AddTemplate(xobject, transform);
                    }


                    index++;
                }

                if (comic.gridAboveAll && comic.showGrid)
                {
                    DrawGrid(cb, width, height, rows, comic);
                }

                //document.Add(new Paragraph("Hello World!"));
                // Close the document

                document.Close();
                // Close the writer instance

                writer.Close();
                // Always close open filehandles explicity
                fs.Close();

                if (hasDrawImages)
                {
                    drawImageZip.Save();
                }
                drawImageZip.Dispose();
            }


            return(false);
        }
Exemple #2
0
        public static async Task <RageItem> createRageItem(string elementName, XmlReader subtree)
        {
            RageItem item = new RageItem();

            switch (elementName)
            {
            case "Face":
                item = new Face();
                break;

            case "Text":
                item = new Text();
                break;

            case "AnyFont":
                item = new AnyFontText();
                break;

            case "Draw":
            case "Image":
                item = new DrawImage();
                break;

            default:
                break;
            }

            while (await subtree.ReadAsync())
            {
                switch (subtree.Name)
                {
                case "itemx":
                    item.x = float.Parse(subtree.ReadInnerXml());
                    break;

                case "itemy":
                    item.y = float.Parse(subtree.ReadInnerXml());
                    break;

                case "opacity":
                    item.opacity = float.Parse(subtree.ReadInnerXml());
                    break;

                case "rotation":
                    item.rotation = float.Parse(subtree.ReadInnerXml());
                    break;

                default:
                    break;
                }

                //Image or Draw
                if (item is DrawImage)
                {
                    switch (subtree.Name)
                    {
                    //DrawImage
                    case "bytes":
                        byte[] decoded = System.Convert.FromBase64String(subtree.ReadInnerXml());
                        ((DrawImage)item).imagedata = decoded;
                        break;

                    default:
                        break;
                    }
                }

                //Text
                if (item is Text)
                {
                    switch (subtree.Name)
                    {
                    case "width":
                        ((Text)item).width = float.Parse(subtree.ReadInnerXml());
                        break;

                    case "height":
                        ((Text)item).height = float.Parse(subtree.ReadInnerXml());
                        break;

                    case "color":
                        ((Text)item).color = "#" + (int.Parse(subtree.ReadInnerXml())).ToString("X").PadLeft(6, "0"[0]);
                        break;

                    case "style":
                        ((Text)item).style = int.Parse(subtree.ReadInnerXml());
                        break;

                    case "size":
                        ((Text)item).size = float.Parse(subtree.ReadInnerXml());
                        break;

                    case "text":
                        ((Text)item).text = HttpUtility.HtmlDecode(subtree.ReadInnerXml());
                        break;

                    case "align":
                        string align = subtree.ReadInnerXml();
                        ((Text)item).align = align == "left" ? Text.ALIGN.LEFT : (align == "right" ? Text.ALIGN.RIGHT : Text.ALIGN.CENTER);
                        break;

                    case "bgOn":
                        ((Text)item).bgOn = bool.Parse(subtree.ReadInnerXml());
                        break;

                    case "bgColor":
                        ((Text)item).bgColor = "#" + (int.Parse(subtree.ReadInnerXml())).ToString("X").PadLeft(6, "0"[0]);
                        break;

                    default:
                        break;
                    }

                    if (item is AnyFontText)
                    {
                        switch (subtree.Name)
                        {
                        case "font":
                            ((AnyFontText)item).font = HttpUtility.HtmlDecode(subtree.ReadInnerXml());
                            break;

                        case "bold":
                            ((AnyFontText)item).bold = bool.Parse(subtree.ReadInnerXml());
                            break;

                        case "italic":
                            ((AnyFontText)item).italic = bool.Parse(subtree.ReadInnerXml());
                            break;

                        case "underline":
                            ((AnyFontText)item).underline = bool.Parse(subtree.ReadInnerXml());
                            break;

                        default:
                            break;
                        }
                    }
                }

                //Face
                if (item is Face)
                {
                    switch (subtree.Name)
                    {
                    case "facename":
                        ((Face)item).file = HttpUtility.UrlDecode(subtree.ReadInnerXml());
                        break;

                    case "scalex":
                        ((Face)item).scalex = float.Parse(subtree.ReadInnerXml());
                        break;

                    case "scaley":
                        ((Face)item).scaley = float.Parse(subtree.ReadInnerXml());
                        break;

                    case "mirrored":
                        ((Face)item).mirrored = bool.Parse(subtree.ReadInnerXml());
                        break;

                    default:
                        break;
                    }
                }
            }

            return(item);
        }