Example #1
0
        public void DoChecksOfAllBooksBackgroundWork(ProgressDialogBackground dialog, string pathToFolderOfReplacementImages)
        {
            var bookInfos = TheOneEditableCollection.GetBookInfos();
            var count     = bookInfos.Count();

            if (count == 0)
            {
                return;
            }

            foreach (var bookInfo in bookInfos)
            {
                //not allowed in this thread: dialog.ProgressBar.Value++;
                dialog.Progress.ProgressIndicator.PercentCompleted += 100 / count;

                var book = _bookServer.GetBookFromBookInfo(bookInfo);

                dialog.Progress.WriteMessage("Checking " + book.TitleBestForUserDisplay);
                book.CheckBook(dialog.Progress, pathToFolderOfReplacementImages);
                dialog.ProgressString.WriteMessage("");
            }
            dialog.ProgressBar.Value++;
        }
Example #2
0
        private void MakeSimplePdf(string inputHtmlPath, string outputPdfPath, string paperSizeName, bool landscape, DoWorkEventArgs doWorkEventArgs)
        {
            var customSizes = new Dictionary <string, string>();

            customSizes.Add("Halfletter", "--page-width 8.5 --page-height 5.5");
            string pageSizeArguments;

            if (!customSizes.TryGetValue(paperSizeName, out pageSizeArguments))
            {
                pageSizeArguments = "--page-size " + paperSizeName;;                  //this works too " --page-width 14.8cm --page-height 21cm"
            }

            //wkhtmltopdf chokes on stuff like chinese file names, even if we put the console code page to UTF 8 first (CHCP 65001)
            //so now, we just deal in temp files
            using (var tempInput = TempFile.WithExtension(".htm"))
            {
                File.Delete(tempInput.Path);
                var source = File.ReadAllText(inputHtmlPath);
                //hide all placeholders

                File.WriteAllText(tempInput.Path, source.Replace("placeholder.png", "").Replace("placeHolder.png", ""));
                //File.Copy(inputHtmlPath, tempInput.Path);
                var tempOutput = TempFile.WithExtension(".pdf");                 //we don't want to dispose of this
                File.Delete(tempOutput.Path);

                /*--------------------------------DEVELOPERS -----------------------------
                 *
                 *	Are you trying to debug a disparity between the HTML preview and
                 *	the PDF output, which should be identical? Some notes:
                 *
                 * 1) Wkhtmltopdf requires different handling of file names for the local
                 * file system than firefox. So if you open this html, do so in Chrome
                 * instead of Firefox.
                 *
                 * 2) Wkhtmltopdf violates the HTML requirement that classes are case
                 * sensitive. So it could be that it is using a rule you forgot you
                 * had, and which is not being triggered by the better browsers.
                 *
                 */
                string exePath = FindWkhtmlToPdf();

                var arguments = string.Format(
                    "--no-background " +
                    //without this, we get a thin line on the right side, which turned into a line in the middle when made into a booklet. You could only see it on paper or by zooming in.
                    " --print-media-type " +
                    pageSizeArguments +
                    (landscape ? " -O Landscape " : "") +
#if DEBUG
                    " --debug-javascript " +
#endif

                    "  --margin-bottom 0mm  --margin-top 0mm  --margin-left 0mm  --margin-right 0mm " +
                    "--disable-smart-shrinking --zoom {0} \"{1}\" \"{2}\"",
                    GetZoomBasedOnScreenDPISettings().ToString(),
                    Path.GetFileName(tempInput.Path), tempOutput.Path);

                ExecutionResult result = null;
                using (var dlg = new ProgressDialogBackground())
                {
                    /* This isn't really working yet (Aug 2012)... I put a day's work into getting Palaso.CommandLineRunner to
                     * do asynchronous reading of the
                     * nice progress that wkhtml2pdf puts out, and feeding it to the UI. It worked find with a sample utility
                     * (PalasoUIWindowsForms.TestApp.exe). But try as I might, it seems
                     * that the Process doesn't actually deliver wkhtml2pdf's outputs to me until it's all over.
                     * If I run wkhtml2pdf from a console, it gives the progress just fine, as it works.
                     * So there is either a bug in Palaso.CommandLineRunner & friends, or.... ?
                     */


                    //this proves that the ui part here is working... it's something about the wkhtml2pdf that we're not getting the updates in real time...
                    //		dlg.ShowAndDoWork(progress => result = CommandLineRunner.Run("PalasoUIWindowsForms.TestApp.exe", "CommandLineRunnerTest", null, string.Empty, 60, progress
                    dlg.ShowAndDoWork((progress, args) =>
                    {
                        progress.WriteStatus("Making PDF...");
                        //this is a trick... since we are so far failing to get
                        //the progress out of wkhtml2pdf until it is done,
                        //we at least have this indicator which on win 7 does
                        //grow from 0 to the set percentage with some animation

                        //nb: Later, on a 100page doc, I did get good progress at the end
                        progress.ProgressIndicator.PercentCompleted = 70;
                        result = CommandLineRunner.Run(exePath, arguments, null, Path.GetDirectoryName(tempInput.Path),
                                                       5 * 60, progress
                                                       , (s) =>
                        {
                            progress.WriteStatus(s);

                            try
                            {
                                //this will hopefully avoid the exception below (which we'll swallow anyhow)
                                if (((BackgroundWorker)args.Argument).IsBusy)
                                {
                                    //this wakes up the dialog, which then calls the Refresh() we need
                                    try
                                    {
                                        ((BackgroundWorker)args.Argument).ReportProgress(100);
                                    }
                                    catch (Exception)
                                    {
                                        //else swallow; we've gotten this error:
                                        //"This operation has already had OperationCompleted called on it and further calls are illegal"
                                                                                                                                                                                                #if DEBUG
                                        throw;
                                                                                                                                                                                                #endif
                                    }
                                }
                                else
                                {
                                                                                                                                                                                        #if DEBUG
                                    Debug.Fail("Wanna look into this? Why is the process still reporting back?");
                                                                                                                                                                                        #endif
                                }
                            }
                            catch (Exception)
                            {
#if DEBUG
                                throw;
#endif
                                //swallow an complaints about it already being completed (bl-233)
                            }
                        });
                    });
                }

                //var progress = new CancellableNullProgress(doWorkEventArgs);


                Debug.WriteLine(result.StandardError);
                Debug.WriteLine(result.StandardOutput);

                if (!File.Exists(tempOutput.Path))
                {
                    throw new ApplicationException("Bloom was not able to create the PDF.\r\n\r\nDetails: Wkhtml2pdf did not produce the expected document.");
                }

                try
                {
                    File.Move(tempOutput.Path, outputPdfPath);
                }
                catch (IOException e)
                {
                    //I can't figure out how it happened (since GetPdfPath makes sure the file name is unique),
                    //but we had a report (BL-211) of that move failing.
                    throw new ApplicationException(
                              string.Format("Bloom tried to save the file to {0}, but Windows said that it was locked. Please try again.\r\n\r\nDetails: {1}",
                                            outputPdfPath, e.Message));
                }
            }
        }
        /// <summary>
        /// Makes the image png if it's not a jpg, makes white transparent, compresses it, and saves in the book's folder.
        /// Replaces any file with the same name.
        /// </summary>
        /// <returns>The name of the file, now in the book's folder.</returns>
        private string ProcessAndCopyImage(PalasoImage imageInfo, string bookFolderPath)
        {
            var isJpeg = ShouldSaveAsJpeg(imageInfo);

            try
            {
                using (Bitmap image = new Bitmap(imageInfo.Image))
                //nb: there are cases (undefined) where we get out of memory if we are not operating on a copy
                {
                    //photographs don't work if you try to make the white transparent
                    if (!isJpeg && image is Bitmap)
                    {
                        ((Bitmap)image).MakeTransparent(Color.White);
                        //make white look realistic against background
                    }

                    string imageFileName = GetImageFileName(bookFolderPath, imageInfo, isJpeg);
                    var    dest          = Path.Combine(bookFolderPath, imageFileName);
                    if (File.Exists(dest))
                    {
                        try
                        {
                            File.Delete(dest);
                        }
                        catch (System.IO.IOException error)
                        {
                            throw new ApplicationException("Bloom could not replace the image " + imageFileName +
                                                           ", probably because Bloom itself has it locked.");
                        }
                    }
                    image.Save(dest, isJpeg ? ImageFormat.Jpeg : ImageFormat.Png);
                    if (!isJpeg)
                    {
                        using (var dlg = new ProgressDialogBackground())
                        {
                            dlg.ShowAndDoWork((progress, args) => ImageUpdater.CompressImage(dest, progress));
                        }
                    }
                    imageInfo.Metadata.Write(dest);

                    return(imageFileName);
                }
            }
            catch (System.IO.IOException)
            {
                throw;                 //these are informative on their own
            }
            catch (Exception error)
            {
                if (!string.IsNullOrEmpty(imageInfo.FileName) && File.Exists(imageInfo.OriginalFilePath))
                {
                    var megs = new System.IO.FileInfo(imageInfo.OriginalFilePath).Length / (1024 * 1000);
                    if (megs > 2)
                    {
                        var msg = string.Format("Bloom was not able to prepare that picture for including in the book. \r\nThis is a rather large image to be adding to a book --{0} Megs--.", megs);
                        if (isJpeg)
                        {
                            msg += "\r\nNote, this file is a jpeg, which is normally used for photographs, not line-drawings (png, tiff, bmp). Bloom can handle smallish jpegs, large ones are difficult to handle, especialy if memory is limitted.";
                        }
                        throw new ApplicationException(msg, error);
                    }
                }

                throw new ApplicationException("Bloom was not able to prepare that picture for including in the book. Is it too large, or an odd format?\r\n" + imageInfo.FileName, error);
            }
        }