int Pdfsync::DocToSource(UINT pageNo, PointI pt, ScopedMem<WCHAR>& filename, UINT *line, UINT *col) { if (IsIndexDiscarded()) if (RebuildIndex() != PDFSYNCERR_SUCCESS) return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED; // find the entry in the index corresponding to this page if (pageNo <= 0 || pageNo >= sheetIndex.Count() || pageNo > (UINT)engine->PageCount()) return PDFSYNCERR_INVALID_PAGE_NUMBER; // PdfSync coordinates are y-inversed RectI mbox = engine->PageMediabox(pageNo).Round(); pt.y = mbox.dy - pt.y; // distance to the closest pdf location (in the range <PDFSYNC_EPSILON_SQUARE) UINT closest_xydist = UINT_MAX; UINT selected_record = UINT_MAX; // If no record is found within a distance^2 of PDFSYNC_EPSILON_SQUARE // (selected_record == -1) then we pick up the record that is closest // vertically to the hit-point. UINT closest_ydist = UINT_MAX; // vertical distance between the hit point and the vertically-closest record UINT closest_xdist = UINT_MAX; // horizontal distance between the hit point and the vertically-closest record UINT closest_ydist_record = UINT_MAX; // vertically-closest record // read all the sections of 'p' declarations for this pdf sheet for (size_t i = sheetIndex.At(pageNo); i < points.Count() && points.At(i).page == pageNo; i++) { // check whether it is closer than the closest point found so far UINT dx = abs(pt.x - (int)SYNC_TO_PDF_COORDINATE(points.At(i).x)); UINT dy = abs(pt.y - (int)SYNC_TO_PDF_COORDINATE(points.At(i).y)); UINT dist = dx * dx + dy * dy; if (dist < PDFSYNC_EPSILON_SQUARE && dist < closest_xydist) { selected_record = points.At(i).record; closest_xydist = dist; } else if ((closest_xydist == UINT_MAX) && dy < PDFSYNC_EPSILON_Y && (dy < closest_ydist || (dy == closest_ydist && dx < closest_xdist))) { closest_ydist_record = points.At(i).record; closest_ydist = dy; closest_xdist = dx; } } if (selected_record == UINT_MAX) selected_record = closest_ydist_record; if (selected_record == UINT_MAX) return PDFSYNCERR_NO_SYNC_AT_LOCATION; // no record was found close enough to the hit point // We have a record number, we need to find its declaration ('l ...') in the syncfile PdfsyncLine cmp; cmp.record = selected_record; PdfsyncLine *found = (PdfsyncLine *)bsearch(&cmp, lines.LendData(), lines.Count(), sizeof(PdfsyncLine), cmpLineRecords); assert(found); if (!found) return PDFSYNCERR_NO_SYNC_AT_LOCATION; filename.Set(str::Dup(srcfiles.At(found->file))); *line = found->line; *col = found->column; return PDFSYNCERR_SUCCESS; }
static void BenchFile(const WCHAR *filePath, const WCHAR *pagesSpec) { if (!file::Exists(filePath)) { return; } // ad-hoc: if enabled times layout instead of rendering and does layout // using all text rendering methods, so that we can compare and find // docs that take a long time to load if (Doc::IsSupportedFile(filePath) && !gGlobalPrefs->ebookUI.useFixedPageUI) { BenchEbookLayout(filePath); return; } if (ChmModel::IsSupportedFile(filePath) && !gGlobalPrefs->chmUI.useFixedPageUI) { BenchChmLoadOnly(filePath); return; } Timer total; logbench(L"Starting: %s", filePath); Timer t; BaseEngine *engine = EngineManager::CreateEngine(filePath); if (!engine) { logbench(L"Error: failed to load %s", filePath); return; } double timeMs = t.Stop(); logbench(L"load: %.2f ms", timeMs); int pages = engine->PageCount(); logbench(L"page count: %d", pages); if (nullptr == pagesSpec) { for (int i = 1; i <= pages; i++) { BenchLoadRender(engine, i); } } assert(!pagesSpec || IsBenchPagesInfo(pagesSpec)); Vec<PageRange> ranges; if (ParsePageRanges(pagesSpec, ranges)) { for (size_t i = 0; i < ranges.Count(); i++) { for (int j = ranges.At(i).start; j <= ranges.At(i).end; j++) { if (1 <= j && j <= pages) BenchLoadRender(engine, j); } } } delete engine; total.Stop(); logbench(L"Finished (in %.2f ms): %s", total.GetTimeInMs(), filePath); }
RectD GetPageRect(int pageNo) { if (preventRecursion) return RectD(); preventRecursion = true; // assume that any engine methods could lead to a seek RectD bbox = engine->PageMediabox(pageNo); bbox = engine->Transform(bbox, pageNo, 1.0, 0); preventRecursion = false; return bbox; }
// returns a list of permissions denied by this document // Caller needs to free the result static WCHAR *FormatPermissions(Controller *ctrl) { if (!ctrl->AsFixed()) return nullptr; WStrVec denials; BaseEngine *engine = ctrl->AsFixed()->GetEngine(); if (!engine->AllowsPrinting()) denials.Push(str::Dup(_TR("printing document"))); if (!engine->AllowsCopyingText()) denials.Push(str::Dup(_TR("copying text"))); return denials.Join(L", "); }
int Pdfsync::SourceToDoc(const WCHAR* srcfilename, UINT line, UINT col, UINT* page, Vec<RectI>& rects) { if (IsIndexDiscarded()) if (RebuildIndex() != PDFSYNCERR_SUCCESS) return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED; Vec<size_t> found_records; UINT ret = SourceToRecord(srcfilename, line, col, found_records); if (ret != PDFSYNCERR_SUCCESS || found_records.size() == 0) return ret; rects.Reset(); // records have been found for the desired source position: // we now find the page and positions in the PDF corresponding to these found records UINT firstPage = UINT_MAX; for (size_t i = 0; i < points.size(); i++) { if (!found_records.Contains(points.at(i).record)) continue; if (firstPage != UINT_MAX && firstPage != points.at(i).page) continue; firstPage = *page = points.at(i).page; RectD rc(SYNC_TO_PDF_COORDINATE(points.at(i).x), SYNC_TO_PDF_COORDINATE(points.at(i).y), MARK_SIZE, MARK_SIZE); // PdfSync coordinates are y-inversed RectD mbox = engine->PageMediabox(firstPage); rc.y = mbox.dy - (rc.y + rc.dy); rects.Push(rc.Round()); } if (rects.size() > 0) return PDFSYNCERR_SUCCESS; // the record does not correspond to any point in the PDF: this is possible... return PDFSYNCERR_NOSYNCPOINT_FOR_LINERECORD; }
IFACEMETHODIMP PreviewBase::GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha) { BaseEngine *engine = GetEngine(); if (!engine) return E_FAIL; RectD page = engine->Transform(engine->PageMediabox(1), 1, 1.0, 0); float zoom = min(cx / (float)page.dx, cx / (float)page.dy) - 0.001f; RectI thumb = RectD(0, 0, page.dx * zoom, page.dy * zoom).Round(); BITMAPINFO bmi = { 0 }; bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader); bmi.bmiHeader.biHeight = thumb.dy; bmi.bmiHeader.biWidth = thumb.dx; bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; unsigned char *bmpData = NULL; HBITMAP hthumb = CreateDIBSection(NULL, &bmi, DIB_RGB_COLORS, (void **)&bmpData, NULL, 0); if (!hthumb) return E_OUTOFMEMORY; page = engine->Transform(thumb.Convert<double>(), 1, zoom, 0, true); RenderedBitmap *bmp = engine->RenderBitmap(1, zoom, 0, &page); HDC hdc = GetDC(NULL); if (bmp && GetDIBits(hdc, bmp->GetBitmap(), 0, thumb.dy, bmpData, &bmi, DIB_RGB_COLORS)) { // cf. http://msdn.microsoft.com/en-us/library/bb774612(v=VS.85).aspx for (int i = 0; i < thumb.dx * thumb.dy; i++) bmpData[4 * i + 3] = 0xFF; *phbmp = hthumb; if (pdwAlpha) *pdwAlpha = WTSAT_RGB; } else { DeleteObject(hthumb); hthumb = NULL; } ReleaseDC(NULL, hdc); delete bmp; return hthumb ? S_OK : E_NOTIMPL; }
static void BenchFile(TCHAR *filePath, const TCHAR *pagesSpec) { if (!file::Exists(filePath)) { return; } Timer total(true); logbench("Starting: %s", filePath); Timer t(true); BaseEngine *engine = EngineManager(!gUseEbookUI).CreateEngine(filePath); t.Stop(); if (!engine) { logbench("Error: failed to load %s", filePath); return; } double timems = t.GetTimeInMs(); logbench("load: %.2f ms", timems); int pages = engine->PageCount(); logbench("page count: %d", pages); if (NULL == pagesSpec) { for (int i = 1; i <= pages; i++) { BenchLoadRender(engine, i); } } assert(!pagesSpec || IsBenchPagesInfo(pagesSpec)); Vec<PageRange> ranges; if (ParsePageRanges(pagesSpec, ranges)) { for (size_t i = 0; i < ranges.Count(); i++) { for (int j = ranges.At(i).start; j <= ranges.At(i).end; j++) { if (1 <= j && j <= pages) BenchLoadRender(engine, j); } } } delete engine; total.Stop(); logbench("Finished (in %.2f ms): %s", total.GetTimeInMs(), filePath); }
IFACEMETHODIMP PreviewBase::DoPreview() { WNDCLASSEX wcex = { 0 }; wcex.cbSize = sizeof(wcex); wcex.lpfnWndProc = PreviewWndProc; wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.lpszClassName = _T("SumatraPDF_PreviewPane"); wcex.style = CS_HREDRAW | CS_VREDRAW; RegisterClassEx(&wcex); m_hwnd = CreateWindow(wcex.lpszClassName, NULL, WS_CHILD | WS_VSCROLL | WS_VISIBLE, m_rcParent.x, m_rcParent.x, m_rcParent.dx, m_rcParent.dy, m_hwndParent, NULL, NULL, NULL); if (!m_hwnd) return HRESULT_FROM_WIN32(GetLastError()); this->renderer = NULL; SetWindowLongPtr(m_hwnd, GWLP_USERDATA, (LONG_PTR)this); BaseEngine *engine = GetEngine(); int pageCount = 1; if (engine) { pageCount = engine->PageCount(); this->renderer = new PageRenderer(engine, m_hwnd); // don't use the engine afterwards directly (cf. PageRenderer::preventRecursion) engine = NULL; } SCROLLINFO si = { 0 }; si.cbSize = sizeof(si); si.fMask = SIF_ALL; si.nPos = 1; si.nMin = 1; si.nMax = pageCount; si.nPage = si.nMax > 1 ? 1 : 2; SetScrollInfo(m_hwnd, SB_VERT, &si, TRUE); ShowWindow(m_hwnd, SW_SHOW); return S_OK; }
/// Initialize the generator virtual StatusCode initialize(const IRndmGen::Param& par) { StatusCode status = RndmGen::initialize(par); if ( status.isSuccess() ) { try { Rndm::DefinedPdf* specs = dynamic_cast<Rndm::DefinedPdf*>(m_params); if ( 0 != specs ) { m_generator = new RandGeneral( &specs->pdf()[0], specs->pdf().size(), specs->interpolation()); BaseEngine* engine = dynamic_cast<BaseEngine*>(m_engine); if ( 0 != engine ) { m_hepEngine = engine->hepEngine(); if ( 0 != m_hepEngine ) { return StatusCode::SUCCESS; } } } } catch (...) { } } return StatusCode::FAILURE; }
virtual void Visit(const WCHAR *name, const WCHAR *url, int level) { PageDestination *dest; if (!url) dest = NULL; else if (IsExternalUrl(url)) dest = new SimpleDest2(0, RectD(), str::Dup(url)); else if (str::FindChar(url, '%')) { ScopedMem<WCHAR> decodedUrl(str::Dup(url)); str::UrlDecodeInPlace(decodedUrl); dest = engine->GetNamedDest(decodedUrl); } else dest = engine->GetNamedDest(url); EbookTocItem *item = new EbookTocItem(str::Dup(name), dest); item->id = ++idCounter; item->open = level <= 2; if (isIndex) { item->pageNo = 0; item->open = level != 1; level++; } AppendTocItem(root, item, level); }
PrintData(BaseEngine *engine, PRINTER_INFO_2 *printerInfo, DEVMODE *devMode, Vec<PRINTPAGERANGE> &ranges, Print_Advanced_Data &advData, int rotation = 0, Vec<SelectionOnPage> *sel = nullptr) : engine(nullptr), advData(advData), rotation(rotation) { if (engine) this->engine = engine->Clone(); if (printerInfo) { printerName.Set(str::Dup(printerInfo->pPrinterName)); } if (devMode) this->devMode.Set((LPDEVMODE)memdup(devMode, devMode->dmSize + devMode->dmDriverExtra)); if (!sel) this->ranges = ranges; else this->sel = *sel; }
void* BaseEngine::_DrawingThread(void* arg) { BaseEngine* engine =(BaseEngine*)arg; int& pages = engine->fPages; std::vector< std::pair<BBitmap*, bool> >& bitmap = engine->fBitmap; std::vector< pthread_mutex_t >& mutex = engine->fMutex; int upperbound = -1; int lowerbound = -1; int pageFuture = -1; int pagePast = -1; int currentPage = -1; int deleteIndex = 0; bool forwardPriority = true; while(true) { pthread_mutex_lock(&gEngineStopMutex); if (engine->fStopThread) { engine->fStopThread = false; pthread_mutex_unlock(&gEngineStopMutex); return nullptr; } pthread_mutex_unlock(&gEngineStopMutex); if (currentPage != engine->fCurrentPageNo) { if (engine->fCurrentPageNo < currentPage) forwardPriority = false; else forwardPriority = true; deleteIndex = 0; currentPage = engine->fCurrentPageNo; pageFuture = pagePast = currentPage; lowerbound = currentPage - engine->fBackwardCache; upperbound = currentPage + engine->fForwardCache; if (lowerbound < 0) lowerbound = 0; if (upperbound >= pages) upperbound = pages - 1; } else { for (; deleteIndex < pages; ++deleteIndex) { pthread_mutex_lock(&mutex[deleteIndex]); if (bitmap[deleteIndex].first != nullptr && (deleteIndex < lowerbound || deleteIndex > upperbound)) { delete bitmap[deleteIndex].first; bitmap[deleteIndex].first = nullptr; pthread_mutex_unlock(&mutex[deleteIndex]); break; } pthread_mutex_unlock(&mutex[deleteIndex]); } if (forwardPriority) { if (pageFuture < upperbound) { ++pageFuture; pthread_mutex_lock(&mutex[pageFuture]); if (bitmap[pageFuture].first == nullptr) { bitmap[pageFuture] = engine->_RenderBitmap(pageFuture); } else if (bitmap[pageFuture].second == true) { delete bitmap[pageFuture].first; bitmap[pageFuture] = engine->_RenderBitmap(pageFuture); } pthread_mutex_unlock(&mutex[pageFuture]); } else if (pagePast > lowerbound) { --pagePast; pthread_mutex_lock(&mutex[pagePast]); if (bitmap[pagePast].first == nullptr) { bitmap[pagePast] = engine->_RenderBitmap(pagePast); } else if (bitmap[pageFuture].second == true) { delete bitmap[pageFuture].first; bitmap[pageFuture] = engine->_RenderBitmap(pageFuture); } pthread_mutex_unlock(&mutex[pagePast]); } else { usleep(1000); } } else { if (pagePast > lowerbound) { --pagePast; pthread_mutex_lock(&mutex[pagePast]); if (bitmap[pagePast].first == nullptr) bitmap[pagePast] = engine->_RenderBitmap(pagePast); pthread_mutex_unlock(&mutex[pagePast]); } else if (pageFuture < upperbound) { ++pageFuture; pthread_mutex_lock(&mutex[pageFuture]); if (bitmap[pageFuture].first == nullptr) bitmap[pageFuture] = engine->_RenderBitmap(pageFuture); pthread_mutex_unlock(&mutex[pageFuture]); } else { usleep(1000); } } } } return nullptr; }
bool PrintFile(const WCHAR *fileName, const WCHAR *printerName, bool displayErrors, const WCHAR *settings) { if (!HasPermission(Perm_PrinterAccess)) return false; ScopedMem<WCHAR> fileName2(path::Normalize(fileName)); BaseEngine *engine = EngineManager::CreateEngine(!gUseEbookUI, fileName2); if (!engine || !engine->AllowsPrinting()) { if (displayErrors) MessageBox(NULL, _TR("Cannot print this file"), _TR("Printing problem."), MB_ICONEXCLAMATION | MB_OK | (IsUIRightToLeft() ? MB_RTLREADING : 0)); return false; } HANDLE printer; bool ok = OpenPrinter((WCHAR *)printerName, &printer, NULL); if (!ok) { if (displayErrors) MessageBox(NULL, _TR("Printer with given name doesn't exist"), _TR("Printing problem."), MB_ICONEXCLAMATION | MB_OK | (IsUIRightToLeft() ? MB_RTLREADING : 0)); return false; } // get printer driver information DWORD needed = 0; GetPrinter(printer, 2, NULL, 0, &needed); ScopedMem<PRINTER_INFO_2> infoData((PRINTER_INFO_2 *)AllocArray<BYTE>(needed)); if (infoData) ok = GetPrinter(printer, 2, (LPBYTE)infoData.Get(), needed, &needed); if (!ok || !infoData || needed <= sizeof(PRINTER_INFO_2)) goto Exit; LONG structSize = DocumentProperties(NULL, printer, /* Handle to our printer. */ (WCHAR *)printerName, /* Name of the printer. */ NULL, /* Asking for size, so */ NULL, /* these are not used. */ 0); /* Zero returns buffer size. */ if (structSize < sizeof(DEVMODE)) { // If failure, inform the user, cleanup and return failure. if (displayErrors) MessageBox(NULL, _TR("Could not obtain Printer properties"), _TR("Printing problem."), MB_ICONEXCLAMATION | MB_OK | (IsUIRightToLeft() ? MB_RTLREADING : 0)); goto Exit; } LPDEVMODE devMode = (LPDEVMODE)malloc(structSize); if (!devMode) goto Exit; // Get the default DevMode for the printer and modify it for your needs. LONG returnCode = DocumentProperties(NULL, printer, (WCHAR *)printerName, devMode, /* The address of the buffer to fill. */ NULL, /* Not using the input buffer. */ DM_OUT_BUFFER); /* Have the output buffer filled. */ if (IDOK != returnCode) { // If failure, inform the user, cleanup and return failure. if (displayErrors) MessageBox(NULL, _TR("Could not obtain Printer properties"), _TR("Printing problem."), MB_ICONEXCLAMATION | MB_OK | (IsUIRightToLeft() ? MB_RTLREADING : 0)); goto Exit; } ClosePrinter(printer); printer = NULL; { Print_Advanced_Data advanced; Vec<PRINTPAGERANGE> ranges; ApplyPrintSettings(settings, engine->PageCount(), ranges, advanced); PrintData pd(engine, infoData, devMode, ranges, advanced); ok = PrintToDevice(pd); if (!ok && displayErrors) MessageBox(NULL, _TR("Couldn't initialize printer"), _TR("Printing problem."), MB_ICONEXCLAMATION | MB_OK | (IsUIRightToLeft() ? MB_RTLREADING : 0)); } Exit: free(devMode); if (printer) ClosePrinter(printer); delete engine; return ok; }
int SyncTex::SourceToDoc(const WCHAR* srcfilename, UINT line, UINT col, UINT *page, Vec<RectI> &rects) { if (IsIndexDiscarded()) if (RebuildIndex() != PDFSYNCERR_SUCCESS) return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED; assert(this->scanner); ScopedMem<WCHAR> srcfilepath; // convert the source file to an absolute path if (PathIsRelative(srcfilename)) srcfilepath.Set(PrependDir(srcfilename)); else srcfilepath.Set(str::Dup(srcfilename)); if (!srcfilepath) return PDFSYNCERR_OUTOFMEMORY; bool isUtf8 = true; char *mb_srcfilepath = str::conv::ToUtf8(srcfilepath); TryAgainAnsi: if (!mb_srcfilepath) return PDFSYNCERR_OUTOFMEMORY; int ret = synctex_display_query(this->scanner, mb_srcfilepath, line, col); free(mb_srcfilepath); // recent SyncTeX versions encode in UTF-8 instead of ANSI if (isUtf8 && -1 == ret) { isUtf8 = false; mb_srcfilepath = str::conv::ToAnsi(srcfilepath); goto TryAgainAnsi; } if (-1 == ret) return PDFSYNCERR_UNKNOWN_SOURCEFILE; if (0 == ret) return PDFSYNCERR_NOSYNCPOINT_FOR_LINERECORD; synctex_node_t node; int firstpage = -1; rects.Reset(); while ((node = synctex_next_result(this->scanner)) != NULL) { if (firstpage == -1) { firstpage = synctex_node_page(node); if (firstpage <= 0 || firstpage > engine->PageCount()) continue; *page = (UINT)firstpage; } if (synctex_node_page(node) != firstpage) continue; RectD rc; rc.x = synctex_node_box_visible_h(node); rc.y = synctex_node_box_visible_v(node) - synctex_node_box_visible_height(node); rc.dx = synctex_node_box_visible_width(node), rc.dy = synctex_node_box_visible_height(node) + synctex_node_box_visible_depth(node); rects.Push(rc.Round()); } if (firstpage <= 0) return PDFSYNCERR_NOSYNCPOINT_FOR_LINERECORD; return PDFSYNCERR_SUCCESS; }
bool PrintFile(const WCHAR *fileName, WCHAR *printerName, bool displayErrors, const WCHAR *settings) { bool ok = false; if (!HasPermission(Perm_PrinterAccess)) return false; ScopedMem<WCHAR> fileName2(path::Normalize(fileName)); BaseEngine *engine = EngineManager::CreateEngine(fileName2, true /* prefer Chm2Engine */); #ifndef DISABLE_DOCUMENT_RESTRICTIONS if (engine && !engine->AllowsPrinting()) { delete engine; engine = NULL; } #endif if (!engine) { if (displayErrors) MessageBoxWarning(NULL, _TR("Cannot print this file"), _TR("Printing problem.")); return false; } HANDLE printer; BOOL res = OpenPrinter(printerName, &printer, NULL); if (0 == res) { if (displayErrors) MessageBoxWarning(NULL, _TR("Printer with given name doesn't exist"), _TR("Printing problem.")); return false; } LPDEVMODE devMode = NULL; // get printer driver information DWORD needed = 0; GetPrinter(printer, 2, NULL, 0, &needed); ScopedMem<PRINTER_INFO_2> infoData((PRINTER_INFO_2 *)AllocArray<BYTE>(needed)); if (infoData) res = GetPrinter(printer, 2, (LPBYTE)infoData.Get(), needed, &needed); if ((0 == res) || !infoData || needed <= sizeof(PRINTER_INFO_2)) goto Exit; LONG structSize = DocumentProperties(NULL, printer, printerName, NULL, /* Asking for size, so */ NULL, /* not used. */ 0); /* Zero returns buffer size. */ if (structSize < sizeof(DEVMODE)) { // If failure, inform the user, cleanup and return failure. if (displayErrors) MessageBoxWarning(NULL, _TR("Could not obtain Printer properties"), _TR("Printing problem.")); goto Exit; } devMode = (LPDEVMODE)malloc(structSize); if (!devMode) goto Exit; // Get the default DevMode for the printer and modify it for your needs. LONG returnCode = DocumentProperties(NULL, printer, printerName, devMode, /* The address of the buffer to fill. */ NULL, /* Not using the input buffer. */ DM_OUT_BUFFER); /* Have the output buffer filled. */ if (IDOK != returnCode) { // If failure, inform the user, cleanup and return failure. if (displayErrors) MessageBoxWarning(NULL, _TR("Could not obtain Printer properties"), _TR("Printing problem.")); goto Exit; } ClosePrinter(printer); printer = NULL; { Print_Advanced_Data advanced; Vec<PRINTPAGERANGE> ranges; ApplyPrintSettings(settings, engine->PageCount(), ranges, advanced, devMode); PrintData pd(engine, infoData, devMode, ranges, advanced); ok = PrintToDevice(pd); if (!ok && displayErrors) MessageBoxWarning(NULL, _TR("Couldn't initialize printer"), _TR("Printing problem.")); } Exit: free(devMode); if (printer) ClosePrinter(printer); delete engine; return ok; }
int main(int argc, char **argv) { setlocale(LC_ALL, "C"); DisableDataExecution(); WStrVec argList; ParseCmdLine(GetCommandLine(), argList); if (argList.Count() < 2) { Usage: ErrOut("%s <filename> [-pwd <password>][-full][-render <path-%%d.tga>]\n", path::GetBaseName(argList.At(0))); return 2; } ScopedMem<WCHAR> filePath; WIN32_FIND_DATA fdata; HANDLE hfind = FindFirstFile(argList.At(1), &fdata); if (INVALID_HANDLE_VALUE != hfind) { ScopedMem<WCHAR> dir(path::GetDir(argList.At(1))); filePath.Set(path::Join(dir, fdata.cFileName)); FindClose(hfind); } else { // embedded documents are referred to by an invalid path // containing more information after a colon (e.g. "C:\file.pdf:3:0") filePath.Set(str::Dup(argList.At(1))); } bool fullDump = false; WCHAR *password = NULL; WCHAR *renderPath = NULL; float renderZoom = 1.f; bool useAlternateHandlers = false; bool loadOnly = false, silent = false; int breakAlloc = 0; for (size_t i = 2; i < argList.Count(); i++) { if (str::Eq(argList.At(i), L"-full")) fullDump = true; else if (str::Eq(argList.At(i), L"-pwd") && i + 1 < argList.Count()) password = argList.At(++i); else if (str::Eq(argList.At(i), L"-render") && i + 1 < argList.Count()) { // optional zoom argument (e.g. -render 50% file.pdf) float zoom; if (i + 2 < argList.Count() && str::Parse(argList.At(i + 1), L"%f%%%$", &zoom) && zoom > 0.f) { renderZoom = zoom / 100.f; i++; } renderPath = argList.At(++i); } // -alt is for debugging alternate rendering methods else if (str::Eq(argList.At(i), L"-alt")) useAlternateHandlers = true; // -loadonly and -silent are only meant for profiling else if (str::Eq(argList.At(i), L"-loadonly")) loadOnly = true; else if (str::Eq(argList.At(i), L"-silent")) silent = true; #ifdef DEBUG else if (str::Eq(argList.At(i), L"-breakalloc") && i + 1 < argList.Count()) breakAlloc = _wtoi(argList.At(++i)); #endif else goto Usage; } #ifdef DEBUG if (breakAlloc) { _CrtSetBreakAlloc(breakAlloc); if (!IsDebuggerPresent()) MessageBox(NULL, L"Keep your debugger ready for the allocation breakpoint...", L"EngineDump", MB_ICONINFORMATION); } #endif if (silent) { FILE *nul; freopen_s(&nul, "NUL", "w", stdout); freopen_s(&nul, "NUL", "w", stderr); } // optionally use GDI+ rendering for PDF/XPS and the original ChmEngine for CHM DebugGdiPlusDevice(useAlternateHandlers); bool useChm2Engine = !useAlternateHandlers; ScopedGdiPlus gdiPlus; DocType engineType; PasswordHolder pwdUI(password); BaseEngine *engine = EngineManager::CreateEngine(filePath, &pwdUI, &engineType, useChm2Engine); if (!engine) { ErrOut("Error: Couldn't create an engine for %s!\n", path::GetBaseName(filePath)); return 1; } Vec<PageAnnotation> *userAnnots = LoadFileModifications(engine->FileName()); engine->UpdateUserAnnotations(userAnnots); delete userAnnots; if (!loadOnly) DumpData(engine, fullDump); if (renderPath) RenderDocument(engine, renderPath, renderZoom, silent); delete engine; #ifdef DEBUG // report memory leaks on stderr for engines that shouldn't leak if (engineType != Engine_DjVu) { _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); } #endif return 0; }
// see http://itexmac.sourceforge.net/pdfsync.html for the specification int Pdfsync::RebuildIndex() { size_t len; ScopedMem<char> data(file::ReadAll(syncfilepath, &len)); if (!data) return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED; // convert the file data into a list of zero-terminated strings str::TransChars(data, "\r\n", "\0\0"); // parse preamble (jobname and version marker) char *line = data; char *dataEnd = data + len; // replace star by spaces (TeX uses stars instead of spaces in filenames) str::TransChars(line, "*/", " \\"); ScopedMem<WCHAR> jobName(str::conv::FromAnsi(line)); jobName.Set(str::Join(jobName, L".tex")); jobName.Set(PrependDir(jobName)); line = Advance0Line(line, dataEnd); UINT versionNumber = 0; if (!line || !str::Parse(line, "version %u", &versionNumber) || versionNumber != 1) return PDFSYNCERR_SYNCFILE_CANNOT_BE_OPENED; // reset synchronizer database srcfiles.Reset(); lines.Reset(); points.Reset(); fileIndex.Reset(); sheetIndex.Reset(); Vec<size_t> filestack; UINT page = 1; sheetIndex.Append(0); // add the initial tex file to the source file stack filestack.Push(srcfiles.Count()); srcfiles.Append(jobName.StealData()); PdfsyncFileIndex findex = { 0 }; fileIndex.Append(findex); PdfsyncLine psline; PdfsyncPoint pspoint; // parse data UINT maxPageNo = engine->PageCount(); while ((line = Advance0Line(line, dataEnd)) != NULL) { if (!line) break; switch (*line) { case 'l': psline.file = filestack.Last(); if (str::Parse(line, "l %u %u %u", &psline.record, &psline.line, &psline.column)) lines.Append(psline); else if (str::Parse(line, "l %u %u", &psline.record, &psline.line)) { psline.column = 0; lines.Append(psline); } // else dbg("Bad 'l' line in the pdfsync file"); break; case 's': if (str::Parse(line, "s %u", &page)) sheetIndex.Append(points.Count()); // else dbg("Bad 's' line in the pdfsync file"); // if (0 == page || page > maxPageNo) // dbg("'s' line with invalid page number in the pdfsync file"); break; case 'p': pspoint.page = page; if (0 == page || page > maxPageNo) /* ignore point for invalid page number */; else if (str::Parse(line, "p %u %u %u", &pspoint.record, &pspoint.x, &pspoint.y)) points.Append(pspoint); else if (str::Parse(line, "p* %u %u %u", &pspoint.record, &pspoint.x, &pspoint.y)) points.Append(pspoint); // else dbg("Bad 'p' line in the pdfsync file"); break; case '(': { ScopedMem<WCHAR> filename(str::conv::FromAnsi(line + 1)); // if the filename contains quotes then remove them // TODO: this should never happen!? if (filename[0] == '"' && filename[str::Len(filename) - 1] == '"') filename.Set(str::DupN(filename + 1, str::Len(filename) - 2)); // undecorate the filepath: replace * by space and / by \ str::TransChars(filename, L"*/", L" \\"); // if the file name extension is not specified then add the suffix '.tex' if (str::IsEmpty(path::GetExt(filename))) filename.Set(str::Join(filename, L".tex")); // ensure that the path is absolute if (PathIsRelative(filename)) filename.Set(PrependDir(filename)); filestack.Push(srcfiles.Count()); srcfiles.Append(filename.StealData()); findex.start = findex.end = lines.Count(); fileIndex.Append(findex); } break; case ')': if (filestack.Count() > 1) fileIndex.At(filestack.Pop()).end = lines.Count(); // else dbg("Unbalanced ')' line in the pdfsync file"); break; default: // dbg("Ignoring invalid pdfsync line starting with '%c'", *line); break; } } fileIndex.At(0).end = lines.Count(); assert(filestack.Count() == 1); return Synchronizer::RebuildIndex(); }