static void CreateThumbnailForDoc(Doc doc, DisplayState& ds) { CrashIf(!doc.AsMobi() && !doc.AsEpub()); if (!ShouldSaveThumbnail(ds)) return; // if there is cover image, we use it to generate thumbnail by scaling // image width to thumbnail dx, scaling height proportionally and using // as much of it as fits in thumbnail dy RenderedBitmap *bmp = ThumbFromCoverPage(doc); if (!bmp) { // no cover image so generate thumbnail from first page SizeI pageSize(THUMBNAIL_DX * 3, THUMBNAIL_DY * 3); SizeI dstSize(THUMBNAIL_DX, THUMBNAIL_DY); bmp = RenderFirstDocPageToBitmap(doc, pageSize, dstSize, 10); } SaveThumbnailForFile(doc.GetFilePath(), bmp); }
static void GetProps(Doc doc, PropertiesLayout *layoutData, DisplayModel *dm, bool extended) { CrashIf(!doc.IsEngine() && !doc.IsEbook()); DocType engineType = doc.GetDocType(); WCHAR *str = str::Dup(gPluginMode ? gPluginURL : doc.GetFilePath()); layoutData->AddProperty(_TR("File:"), str); str = doc.GetProperty(Prop_Title); layoutData->AddProperty(_TR("Title:"), str); str = doc.GetProperty(Prop_Subject); layoutData->AddProperty(_TR("Subject:"), str); str = doc.GetProperty(Prop_Author); layoutData->AddProperty(_TR("Author:"), str); str = doc.GetProperty(Prop_Copyright); layoutData->AddProperty(_TR("Copyright:"), str); str = doc.GetProperty(Prop_CreationDate); if (Engine_PDF == engineType) ConvDateToDisplay(&str, PdfDateParse); else if (Engine_XPS == engineType) ConvDateToDisplay(&str, IsoDateParse); else if (Engine_Epub == engineType || Doc_Epub == engineType) ConvDateToDisplay(&str, IsoDateParse); else if (Engine_Mobi == engineType || Doc_Mobi == engineType) ConvDateToDisplay(&str, IsoDateParse); layoutData->AddProperty(_TR("Created:"), str); str = doc.GetProperty(Prop_ModificationDate); if (Engine_PDF == engineType) ConvDateToDisplay(&str, PdfDateParse); else if (Engine_XPS == engineType) ConvDateToDisplay(&str, IsoDateParse); else if (Engine_Epub == engineType || Doc_Epub == engineType) ConvDateToDisplay(&str, IsoDateParse); else if (Engine_Mobi == engineType || Doc_Mobi == engineType) ConvDateToDisplay(&str, IsoDateParse); layoutData->AddProperty(_TR("Modified:"), str); str = doc.GetProperty(Prop_CreatorApp); layoutData->AddProperty(_TR("Application:"), str); str = doc.GetProperty(Prop_PdfProducer); // TODO: remove PDF from string layoutData->AddProperty(_TR("PDF Producer:"), str); str = doc.GetProperty(Prop_PdfVersion); layoutData->AddProperty(_TR("PDF Version:"), str); str = FormatPdfFileStructure(doc); layoutData->AddProperty(_TR("PDF Optimizations:"), str); size_t fileSize = file::GetSize(doc.GetFilePath()); if (fileSize == INVALID_FILE_SIZE && doc.IsEngine()) free(doc.AsEngine()->GetFileData(&fileSize)); if (fileSize != INVALID_FILE_SIZE) { str = FormatFileSize(fileSize); layoutData->AddProperty(_TR("File Size:"), str); } if (doc.IsEngine()) { str = str::Format(L"%d", doc.AsEngine()->PageCount()); layoutData->AddProperty(_TR("Number of Pages:"), str); } if (dm && dm->engineType != Engine_Chm) { str = FormatPageSize(dm->engine, dm->CurrentPageNo(), dm->Rotation()); if (IsUIRightToLeft() && IsVistaOrGreater()) { // ensure that the size remains ungarbled left-to-right // (note: XP doesn't know about \u202A...\u202C) str = str::Format(L"\u202A%s\u202C", ScopedMem<WCHAR>(str)); } layoutData->AddProperty(_TR("Page Size:"), str); } str = FormatPermissions(doc); layoutData->AddProperty(_TR("Denied Permissions:"), str); #if defined(DEBUG) || defined(ENABLE_EXTENDED_PROPERTIES) if (extended) { // TODO: FontList extraction can take a while str = doc.GetProperty(Prop_FontList); if (str) { // add a space between basic and extended file properties layoutData->AddProperty(L" ", str::Dup(L" ")); } layoutData->AddProperty(_TR("Fonts:"), str); } #endif }
void OpenMobiInWindow(Doc doc, SumatraWindow& winToReplace) { const TCHAR *fullPath = doc.GetFilePath(); DisplayState *ds = gFileHistory.Find(fullPath); if (gGlobalPrefs.rememberOpenedFiles) { ds = gFileHistory.MarkFileLoaded(fullPath); if (gGlobalPrefs.showStartPage && ds) { // TODO: do it on a background thread? CreateThumbnailForDoc(doc, *ds); } SavePrefs(); } int startReparseIdx = -1; if (ds) startReparseIdx = ds->reparseIdx; // Add the file also to Windows' recently used documents (this doesn't // happen automatically on drag&drop, reopening from history, etc.) if (HasPermission(Perm_DiskAccess) && !gPluginMode) SHAddToRecentDocs(SHARD_PATH, fullPath); ScopedMem<TCHAR> winTitle(str::Format(_T("%s - %s"), path::GetBaseName(fullPath), SUMATRA_WINDOW_TITLE)); if (winToReplace.AsEbookWindow()) { EbookWindow *mw = winToReplace.AsEbookWindow(); CrashIf(!mw); mw->ebookController->SetDoc(doc); win::SetText(mw->hwndFrame, winTitle); // TODO: if we have window position/last position for this file, restore it return; } RectI windowPos = gGlobalPrefs.windowPos; if (!windowPos.IsEmpty()) EnsureAreaVisibility(windowPos); else windowPos = GetDefaultWindowPos(); if (ds && !ds->windowPos.IsEmpty()) { // Make sure it doesn't have a position like outside of the screen etc. windowPos = ShiftRectToWorkArea(ds->windowPos); } WindowInfo *winInfo = winToReplace.AsWindowInfo(); bool wasMaximized = false; if (winInfo && winInfo->hwndFrame) wasMaximized = IsZoomed(winInfo->hwndFrame); CloseDocumentAndDeleteWindowInfo(winInfo); HWND hwnd = CreateWindow( MOBI_FRAME_CLASS_NAME, SUMATRA_WINDOW_TITLE, WS_OVERLAPPEDWINDOW, windowPos.x, windowPos.y, windowPos.dx, windowPos.dy, NULL, NULL, ghinst, NULL); if (!hwnd) return; if (HasPermission(Perm_DiskAccess) && !gPluginMode) DragAcceptFiles(hwnd, TRUE); if (Touch::SupportsGestures()) { GESTURECONFIG gc = { 0, GC_ALLGESTURES, 0 }; Touch::SetGestureConfig(hwnd, 0, 1, &gc, sizeof(GESTURECONFIG)); } EbookWindow *win = new EbookWindow(); win->ebookControls = CreateEbookControls(hwnd); win->hwndWrapper = win->ebookControls->mainWnd; win->ebookController = new EbookController(win->ebookControls); win->hwndFrame = hwnd; gEbookWindows.Append(win); win::SetText(win->hwndFrame, winTitle); SetMenu(hwnd, BuildMenu(win)); ShowWindow(hwnd, wasMaximized ? SW_SHOWMAXIMIZED : SW_SHOW); win->ebookController->SetDoc(doc, startReparseIdx); }
void OpenMobiInWindow(Doc doc, SumatraWindow& winToReplace) { const WCHAR *fullPath = doc.GetFilePath(); DisplayState *ds = gFileHistory.Find(fullPath); if (doc.IsNone()) { // TODO: a hack. In LoadDocumentOld(), if current window IsAboutWindow(), // we set loadedFilePath to prevent a crash if multiple ebook files are // dropped on about window. We need to undo that in case of failure // or else the window will be stuck in an invalid state (not about window // but not a document window either) WindowInfo *w = winToReplace.AsWindowInfo(); if (str::Eq(w->loadedFilePath, doc.GetFilePath())) { free(w->loadedFilePath); w->loadedFilePath = NULL; // this is now about window. We don't want to show it if we're already // showing other windows (the scenario: dragging ebook file on a window // showing a document, we create invisible window for this document and // we don't want to show empty window if loading fails if (gEbookWindows.Count() > 0 || gWindows.Count() > 1) { CloseWindow(w, false); if (gFileHistory.MarkFileInexistent(fullPath)) prefs::Save(); // TODO: notify the use that loading failed (e.g. show a notification) return; } } // TODO: notify the user that loading failed (e.g. show a notification) // TODO: this is not a great solution. In case of opening // file from cmd-line, we create a window but don't show it // if loading afils, we have to show the window. If window // is already visible, this is a no-op ShowWindow(winToReplace.HwndFrame(), SW_SHOW); if (gFileHistory.MarkFileInexistent(fullPath)) prefs::Save(); return; } if (gGlobalPrefs->rememberOpenedFiles) { ds = gFileHistory.MarkFileLoaded(fullPath); if (gGlobalPrefs->showStartPage) { // TODO: do it on a background thread? CreateThumbnailForDoc(doc, *ds); } prefs::Save(); } int startReparseIdx = -1; if (ds && gGlobalPrefs->rememberStatePerDocument && !ds->useDefaultState) startReparseIdx = ds->reparseIdx; // Add the file also to Windows' recently used documents (this doesn't // happen automatically on drag&drop, reopening from history, etc.) if (HasPermission(Perm_DiskAccess) && !gPluginMode) SHAddToRecentDocs(SHARD_PATH, fullPath); ScopedMem<WCHAR> winTitle(str::Format(L"%s - %s", path::GetBaseName(fullPath), SUMATRA_WINDOW_TITLE)); if (winToReplace.AsEbookWindow()) { EbookWindow *mw = winToReplace.AsEbookWindow(); CrashIf(!mw); mw->ebookController->SetDoc(doc); win::SetText(mw->hwndFrame, winTitle); // TODO: if we have window position/last position for this file, restore it return; } RectI windowPos = gGlobalPrefs->windowPos; if (!windowPos.IsEmpty()) EnsureAreaVisibility(windowPos); else windowPos = GetDefaultWindowPos(); if (ds && !ds->windowPos.IsEmpty()) { // Make sure it doesn't have a position like outside of the screen etc. windowPos = ShiftRectToWorkArea(ds->windowPos); } WindowInfo *winInfo = winToReplace.AsWindowInfo(); bool wasMaximized = false; if (winInfo && winInfo->hwndFrame) { wasMaximized = IsZoomed(winInfo->hwndFrame); // hide the window instead of destroying it so that // windows doesn't set a window from a different // process as foreground window instead of the once // created below ShowWindow(winInfo->hwndFrame, SW_HIDE); } HWND hwnd = CreateWindow( MOBI_FRAME_CLASS_NAME, SUMATRA_WINDOW_TITLE, WS_OVERLAPPEDWINDOW, windowPos.x, windowPos.y, windowPos.dx, windowPos.dy, NULL, NULL, ghinst, NULL); if (!hwnd) { CloseDocumentAndDeleteWindowInfo(winInfo); return; } if (HasPermission(Perm_DiskAccess) && !gPluginMode) DragAcceptFiles(hwnd, TRUE); if (Touch::SupportsGestures()) { GESTURECONFIG gc = { 0, GC_ALLGESTURES, 0 }; Touch::SetGestureConfig(hwnd, 0, 1, &gc, sizeof(GESTURECONFIG)); } EbookWindow *win = new EbookWindow(); win->ebookControls = CreateEbookControls(hwnd); win->hwndWrapper = win->ebookControls->mainWnd; win->ebookController = new EbookController(win->ebookControls); win->hwndFrame = hwnd; gEbookWindows.Append(win); win::SetText(win->hwndFrame, winTitle); SetMenu(hwnd, BuildMenu(win)); ShowWindow(hwnd, wasMaximized ? SW_SHOWMAXIMIZED : SW_SHOW); win->ebookController->SetDoc(doc, startReparseIdx); CloseDocumentAndDeleteWindowInfo(winInfo); }