/// <summary> /// Usually we expect that a file at the same path but with extension .svg will /// be found and returned. Failing this we try for one ending in .png. If this still fails we /// start a process to generate an image from the template page content. /// </summary> /// <returns>Should always return a valid image path, unless we really can't come up with an image at all.</returns> private string FindOrGenerateThumbnail(string expectedPathOfThumbnailImage) { var localPath = AdjustPossibleLocalHostPathToFilePath(expectedPathOfThumbnailImage); var svgpath = Path.ChangeExtension(localPath, "svg"); if (RobustFile.Exists(svgpath)) { return(svgpath); } var pngpath = Path.ChangeExtension(localPath, "png"); bool mustRegenerate = false; if (RobustFile.Exists(pngpath)) { var f = new FileInfo(pngpath); if (f.IsReadOnly) { return(pngpath); // it's locked, don't try and replace it } if (!IsPageTypeFromCurrentBook(localPath)) { return(pngpath); } mustRegenerate = true; // prevent thumbnailer using cached (obsolete) image } var altpath = GetAlternativeWritablePath(pngpath); if (RobustFile.Exists(altpath)) { if (!IsPageTypeFromCurrentBook(localPath)) { return(altpath); } mustRegenerate = true; // prevent thumbnailer using cached (obsolete) image } // We don't have an image, or we want to make a fresh one var templatesDirectoryInTemplateBook = Path.GetDirectoryName(expectedPathOfThumbnailImage); var bookPath = Path.GetDirectoryName(templatesDirectoryInTemplateBook); var templateBook = _bookFactory(new BookInfo(bookPath, false), _storageFactory(bookPath)); //note: the caption is used here as a key to find the template page. var caption = Path.GetFileNameWithoutExtension(expectedPathOfThumbnailImage).Trim(); var isLandscape = caption.EndsWith("-landscape"); // matches string in page-chooser.ts if (isLandscape) { caption = caption.Substring(0, caption.Length - "-landscape".Length); } var isSquare = caption.EndsWith("-square"); if (isSquare) { caption = caption.Substring(0, caption.Length - "-square".Length); } // The Replace of & with + corresponds to a replacement made in page-chooser.ts method loadPagesFromCollection. // The Trim is needed because template may now be created by users editing the pageLabel div, and those // labels typically include a trailing newline. IPage templatePage = templateBook.GetPages().FirstOrDefault(page => page.Caption.Replace("&", "+").Trim() == caption); if (templatePage == null) { templatePage = templateBook.GetPages().FirstOrDefault(); // may get something useful?? or throw?? } Image thumbnail = _thumbNailer.GetThumbnailForPage(templateBook, templatePage, isLandscape, isSquare, mustRegenerate); // lock to avoid BL-3781 where we got a "Object is currently in use elsewhere" while doing the Clone() below. // Note: it would appear that the clone isn't even needed, since it was added in the past to overcome this // same contention problem (but, in hindsight, only partially, see?). But for some reason if we just lock the image // until it is saved, we get all gray rectangles. So for now, we just quickly do the clone and unlock. var resultPath = ""; Bitmap clone; // Review: the coarse lock(SyncObj) in BloomServer.ProcessRequest() may have removed the need for this finer grained lock. lock (thumbnail) { clone = new Bitmap((Image)thumbnail.Clone()); } using (clone) { try { //if the directory doesn't exist in the template's directory, make it (i.e. "templates/"). Directory.CreateDirectory(templatesDirectoryInTemplateBook); //save this thumbnail so that we don't have to generate it next time clone.Save(pngpath); resultPath = pngpath; } catch (Exception) { var folder = Path.GetDirectoryName(altpath); Directory.CreateDirectory(folder); clone.Save(altpath); resultPath = altpath; } } return(resultPath); }
/// <summary> /// Usually we expect that a file at the same path but with extension .svg will /// be found and returned. Failing this we try for one ending in .png. If this still fails we /// start a process to generate an image from the template page content. /// </summary> /// <param name="expectedPathOfThumbnailImage"></param> /// <returns>Should always return true, unless we really can't come up with an image at all.</returns> private string FindOrGenerateThumbnail(string expectedPathOfThumbnailImage) { var localPath = AdjustPossibleLocalHostPathToFilePath(expectedPathOfThumbnailImage); var svgpath = Path.ChangeExtension(localPath, "svg"); if (RobustFile.Exists(svgpath)) { return(svgpath); } var pngpath = Path.ChangeExtension(localPath, "png"); bool mustRegenerate = false; if (RobustFile.Exists(pngpath)) { var f = new FileInfo(pngpath); if (f.IsReadOnly) { return(pngpath); // it's locked, don't try and replace it } //If there is no svg, then we assume the we are using a generated image. //If the book we want a thumbnail from is the one is the one we are currently editing, //then the thumbnail we generated last time might not reflect how the page is laid out //now. So in that case we ignore the existing png thumbnail (and any cached version //of it we previously saved) and make a new one. Bloom saves the current page //before invoking AddPage, so the file contains the right content for making the new one. var testLocalPath = localPath.Replace("/", "\\"); var testFolderPath = _bookSelection.CurrentSelection.FolderPath.Replace("/", "\\"); if (Platform.IsWindows) { // Not a formality, since localPath comes from GetBookTemplatePaths and has been // forced to LC on Windows, while the book's FolderPath has not. testLocalPath = testLocalPath.ToLowerInvariant(); testFolderPath = testFolderPath.ToLowerInvariant(); } if (!testLocalPath.Contains(testFolderPath)) { return(pngpath); } mustRegenerate = true; // prevent thumbnailer using cached (obsolete) image } // We don't have an image, or we want to make a fresh one var templatesDirectoryInTemplateBook = Path.GetDirectoryName(expectedPathOfThumbnailImage); var bookPath = Path.GetDirectoryName(templatesDirectoryInTemplateBook); var templateBook = _bookFactory(new BookInfo(bookPath, false), _storageFactory(bookPath)); //note: the caption is used here as a key to find the template page. var caption = Path.GetFileNameWithoutExtension(expectedPathOfThumbnailImage).Trim(); var isLandscape = caption.EndsWith("-landscape"); // matches string in page-chooser.ts if (isLandscape) { caption = caption.Substring(0, caption.Length - "-landscape".Length); } // The Replace of & with + corresponds to a replacement made in page-chooser.ts method loadPagesFromCollection. // The Trim is needed because template may now be created by users editing the pageLabel div, and those // labels typically include a trailing newline. IPage templatePage = templateBook.GetPages().FirstOrDefault(page => page.Caption.Replace("&", "+").Trim() == caption); if (templatePage == null) { templatePage = templateBook.GetPages().FirstOrDefault(); // may get something useful?? or throw?? } Image thumbnail = _thumbNailer.GetThumbnailForPage(templateBook, templatePage, isLandscape, mustRegenerate); // lock to avoid BL-3781 where we got a "Object is currently in use elsewhere" while doing the Clone() below. // Note: it would appear that the clone isn't even needed, since it was added in the past to overcome this // same contention problem (but, in hindsight, only partially, see?). But for some reason if we just lock the image // until it is saved, we get all gray rectangles. So for now, we just quickly do the clone and unlock. var resultPath = ""; Bitmap clone; // Review: the coarse lock(SyncObj) in EnhancedImageServer.ProcessRequest() may have removed the need for this finer grained lock. lock (thumbnail) { clone = new Bitmap((Image)thumbnail.Clone()); } using (clone) { try { //if the directory doesn't exist in the template's directory, make it (i.e. "templates/"). Directory.CreateDirectory(templatesDirectoryInTemplateBook); //save this thumbnail so that we don't have to generate it next time clone.Save(pngpath); resultPath = pngpath; } catch (Exception) { using (var file = new TempFile()) { clone.Save(file.Path); resultPath = file.Path; } } } return(resultPath); }