Ejemplo n.º 1
0
        ///  <summary>
        ///
        ///  </summary>
        /// <param name="specs">All the information about what sort of PDF file to make where</param>
        /// <param name="worker">If not null, the Background worker which is running this task, and may be queried to determine whether a cancel is being attempted</param>
        /// <param name="doWorkEventArgs">The event passed to the worker when it was started. If a cancel is successful, it's Cancel property should be set true.</param>
        /// <param name="owner">A control which can be used to invoke parts of the work which must be done on the ui thread.</param>
        public void MakePdf(PdfMakingSpecs specs, BackgroundWorker worker, DoWorkEventArgs doWorkEventArgs, Control owner)
        {
            // Try up to 4 times. This is a last-resort attempt to handle BL-361.
            // Most likely that was caused by a race condition in MakePdfUsingGeckofxHtmlToPdfComponent.MakePdf,
            // but as it was an intermittent problem and we're not sure that was the cause, this might help.
            for (int i = 0; i < 4; i++)
            {
                new MakePdfUsingGeckofxHtmlToPdfProgram().MakePdf(specs,
                                                                  owner, worker, doWorkEventArgs);

                if (doWorkEventArgs.Cancel || (doWorkEventArgs.Result != null && doWorkEventArgs.Result is Exception))
                {
                    return;
                }
                if (RobustFile.Exists(specs.OutputPdfPath))
                {
                    break;                     // normally the first time
                }
            }
            if (!RobustFile.Exists(specs.OutputPdfPath) && owner != null)
            {
                // Should never happen, but...
                owner.Invoke((Action)(() =>
                {
                    // Review: should we localize this? Hopefully the user never sees it...don't want to increase burden on localizers...
                    MessageBox.Show(
                        "Bloom unexpectedly failed to create the PDF. If this happens repeatedy please report it to the developers. Probably it will work if you just try again.",
                        "Pdf creation failed", MessageBoxButtons.OK);
                }));
                doWorkEventArgs.Result = MakingPdfFailedException.CreatePdfException();
                return;
            }

            try
            {
                // Shrink the PDF file, especially if it has large color images.  (BL-3721)
                // Also if the book is full bleed we need to remove some spurious pages.
                // Removing spurious pages must be done BEFORE we switch pages around to make a booklet!
                // Note: previously compression was the last step, after making a booklet. We moved it before for
                // the reason above. Seems like it would also have performance benefits, if anything, to shrink
                // the file before manipulating it further. Just noting it in case there are unexpected issues.
                var fixPdf = new ProcessPdfWithGhostscript(ProcessPdfWithGhostscript.OutputType.DesktopPrinting, worker);
                fixPdf.ProcessPdfFile(specs.OutputPdfPath, specs.OutputPdfPath, specs.BookIsFullBleed);
                if (specs.BookletPortion != PublishModel.BookletPortions.AllPagesNoBooklet || specs.PrintWithFullBleed)
                {
                    //remake the pdf by reording the pages (and sometimes rotating, shrinking, etc)
                    MakeBooklet(specs);
                }

                // Check that we got a valid, readable PDF.
                // If we get a reliable fix to BL-932 we can take this out altogether.
                // It's probably redundant, since the compression process would probably fail with this
                // sort of corruption, and we are many generations beyond gecko29 where we observed it.
                // However, we don't have data to reliably reproduce the BL-932, and the check doesn't take
                // long, so leaving it in for now.
                CheckPdf(specs.OutputPdfPath);
            }
            catch (KeyNotFoundException e)
            {
                // This is characteristic of BL-932, where Gecko29 fails to make a valid PDF, typically
                // because the user has embedded a really huge image, something like 4000 pixels wide.
                // We think it could also happen with a very long book or if the user is short of memory.
                // The resulting corruption of the PDF file takes the form of a syntax error in an embedded
                // object so that the parser finds an empty string where it expected a 'generationNumber'
                // (currently line 106 of Parser.cs). This exception is swallowed but leads to an empty
                // externalIDs dictionary in PdfImportedObjectTable, and eventually a new exception trying
                // to look up an object ID at line 121 of that class. We catch that exception here and
                // suggest possible actions the user can take until we find a better solution.
                SIL.Reporting.ErrorReport.NotifyUserOfProblem(e,
                                                              LocalizationManager.GetString("PublishTab.PdfMaker.BadPdf", "Bloom had a problem making a PDF of this book. You may need technical help or to contact the developers. But here are some things you can try:")
                                                              + Environment.NewLine + "- "
                                                              + LocalizationManager.GetString("PublishTab.PdfMaker.TryRestart", "Restart your computer and try this again right away")
                                                              + Environment.NewLine + "- "
                                                              +
                                                              LocalizationManager.GetString("PublishTab.PdfMaker.TrySmallerImages",
                                                                                            "Replace large, high-resolution images in your document with lower-resolution ones")
                                                              + Environment.NewLine + "- "
                                                              + LocalizationManager.GetString("PublishTab.PdfMaker.TryMoreMemory", "Try doing this on a computer with more memory"));

                RobustFile.Move(specs.OutputPdfPath, specs.OutputPdfPath + "-BAD");
                doWorkEventArgs.Result = MakingPdfFailedException.CreatePdfException();
            }
        }
Ejemplo n.º 2
0
        ///  <summary>
        ///
        ///  </summary>
        /// <param name="inputHtmlPath"></param>
        /// <param name="outputPdfPath"></param>
        /// <param name="paperSizeName">A0,A1,A2,A3,A4,A5,A6,A7,A8,A9,B0,B1,B10,B2,B3,B4,B5,B6,B7,B8,B9,C5E,Comm10E,DLE,Executive,Folio,Ledger,Legal,Letter,Tabloid</param>
        /// <param name="landscape">true if landscape orientation, false if portrait orientation</param>
        /// <param name="saveMemoryMode">true if PDF file is to be produced using less memory (but more time)</param>
        /// <param name="layoutPagesForRightToLeft">true if RTL, false if LTR layout</param>
        /// <param name="booketLayoutMethod">NoBooklet,SideFold,CutAndStack,Calendar</param>
        /// <param name="bookletPortion">None,AllPagesNoBooklet,BookletCover,BookletPages,InnerContent</param>
        /// <param name="worker">If not null, the Background worker which is running this task, and may be queried to determine whether a cancel is being attempted</param>
        /// <param name="doWorkEventArgs">The event passed to the worker when it was started. If a cancel is successful, it's Cancel property should be set true.</param>
        /// <param name="owner">A control which can be used to invoke parts of the work which must be done on the ui thread.</param>
        public void MakePdf(string inputHtmlPath, string outputPdfPath, string paperSizeName, bool landscape, bool saveMemoryMode, bool layoutPagesForRightToLeft,
                            PublishModel.BookletLayoutMethod booketLayoutMethod, PublishModel.BookletPortions bookletPortion, BackgroundWorker worker, DoWorkEventArgs doWorkEventArgs, Control owner)
        {
            // Try up to 4 times. This is a last-resort attempt to handle BL-361.
            // Most likely that was caused by a race condition in MakePdfUsingGeckofxHtmlToPdfComponent.MakePdf,
            // but as it was an intermittent problem and we're not sure that was the cause, this might help.
            for (int i = 0; i < 4; i++)
            {
                new MakePdfUsingGeckofxHtmlToPdfProgram().MakePdf(inputHtmlPath, outputPdfPath, paperSizeName, landscape, saveMemoryMode,
                                                                  owner, worker, doWorkEventArgs);

                if (doWorkEventArgs.Cancel || (doWorkEventArgs.Result != null && doWorkEventArgs.Result is Exception))
                {
                    return;
                }
                if (RobustFile.Exists(outputPdfPath))
                {
                    break;                     // normally the first time
                }
            }
            if (!RobustFile.Exists(outputPdfPath) && owner != null)
            {
                // Should never happen, but...
                owner.Invoke((Action)(() =>
                {
                    // Review: should we localize this? Hopefully the user never sees it...don't want to increase burden on localizers...
                    MessageBox.Show(
                        "Bloom unexpectedly failed to create the PDF. If this happens repeatedy please report it to the developers. Probably it will work if you just try again.",
                        "Pdf creation failed", MessageBoxButtons.OK);
                }));
            }

            try
            {
                if (bookletPortion != PublishModel.BookletPortions.AllPagesNoBooklet)
                {
                    //remake the pdf by reording the pages (and sometimes rotating, shrinking, etc)
                    MakeBooklet(outputPdfPath, paperSizeName, booketLayoutMethod, layoutPagesForRightToLeft);
                }
                else
                {
                    // Just check that we got a valid, readable PDF. (MakeBooklet has to read the PDF itself,
                    // so we don't need to do this check if we're calling that.)
                    // If we get a reliable fix to BL-932 we can take this 'else' out altogether.
                    CheckPdf(outputPdfPath);
                }
                // Shrink the PDF file, especially if it has large color images.  (BL-3721)
                var fixPdf = new ProcessPdfWithGhostscript(ProcessPdfWithGhostscript.OutputType.DesktopPrinting, worker);
                fixPdf.ProcessPdfFile(outputPdfPath, outputPdfPath);
            }
            catch (KeyNotFoundException e)
            {
                // This is characteristic of BL-932, where Gecko29 fails to make a valid PDF, typically
                // because the user has embedded a really huge image, something like 4000 pixels wide.
                // We think it could also happen with a very long book or if the user is short of memory.
                // The resulting corruption of the PDF file takes the form of a syntax error in an embedded
                // object so that the parser finds an empty string where it expected a 'generationNumber'
                // (currently line 106 of Parser.cs). This exception is swallowed but leads to an empty
                // externalIDs dictionary in PdfImportedObjectTable, and eventually a new exception trying
                // to look up an object ID at line 121 of that class. We catch that exception here and
                // suggest possible actions the user can take until we find a better solution.
                SIL.Reporting.ErrorReport.NotifyUserOfProblem(e,
                                                              LocalizationManager.GetString("PublishTab.PdfMaker.BadPdf", "Bloom had a problem making a PDF of this book. You may need technical help or to contact the developers. But here are some things you can try:")
                                                              + Environment.NewLine + "- "
                                                              + LocalizationManager.GetString("PublishTab.PdfMaker.TryRestart", "Restart your computer and try this again right away")
                                                              + Environment.NewLine + "- "
                                                              +
                                                              LocalizationManager.GetString("PublishTab.PdfMaker.TrySmallerImages",
                                                                                            "Replace large, high-resolution images in your document with lower-resolution ones")
                                                              + Environment.NewLine + "- "
                                                              + LocalizationManager.GetString("PublishTab.PdfMaker.TryMoreMemory", "Try doing this on a computer with more memory"));
            }
        }