RenderedBitmap *RenderFirstDocPageToBitmap(Doc doc, SizeI pageSize, SizeI bmpSize, int border) { PoolAllocator textAllocator; HtmlFormatterArgs *args = CreateFormatterArgsDoc(doc, pageSize.dx - 2 * border, pageSize.dy - 2 * border, &textAllocator); HtmlFormatter *formatter = CreateFormatter(doc, args); HtmlPage *pd = formatter->Next(); delete formatter; delete args; if (!pd) return NULL; Bitmap pageBmp(pageSize.dx, pageSize.dy, PixelFormat24bppRGB); Graphics g(&pageBmp); Rect r(0, 0, pageSize.dx, pageSize.dy); r.Inflate(1, 1); SolidBrush br(Color(255, 255, 255)); g.FillRectangle(&br, r); DrawHtmlPage(&g, &pd->instructions, (REAL)border, (REAL)border, false, &Color(Color::Black)); delete pd; Bitmap res(bmpSize.dx, bmpSize.dy, PixelFormat24bppRGB); Graphics g2(&res); g2.SetInterpolationMode(InterpolationModeHighQualityBicubic); g2.DrawImage(&pageBmp, Rect(0, 0, bmpSize.dx, bmpSize.dy), 0, 0, pageSize.dx, pageSize.dy, UnitPixel); HBITMAP hbmp; Status ok = res.GetHBITMAP(Color::White, &hbmp); if (ok != Ok) return NULL; return new RenderedBitmap(hbmp, bmpSize); }
static int FormatWholeDoc(Doc& doc) { int PAGE_DX = 640; int PAGE_DY = 520; PoolAllocator textAllocator; HtmlFormatterArgs *formatterArgs = CreateFormatterArgsDoc(doc, PAGE_DX, PAGE_DY, &textAllocator); HtmlFormatter *formatter = doc.CreateFormatter(formatterArgs); int nPages = 0; for (HtmlPage *pd = formatter->Next(); pd; pd = formatter->Next()) { delete pd; ++nPages; } delete formatterArgs; delete formatter; return nPages; }
// layout pages from a given reparse point (beginning if NULL) // returns true if layout thread was cancelled bool EbookFormattingThread::Format(int reparseIdx) { bool fromBeginning = (0 == reparseIdx); //lf("Started laying out mobi, fromBeginning=%d", (int)fromBeginning); int totalPageCount = 0; Timer t(true); formatterArgs->reparseIdx = reparseIdx; HtmlFormatter *formatter = CreateFormatter(doc, formatterArgs); int lastReparseIdx = reparseIdx; for (HtmlPage *pd = formatter->Next(); pd; pd = formatter->Next()) { CrashIf(pd->reparseIdx < lastReparseIdx); lastReparseIdx = pd->reparseIdx; if (WasCancelRequested()) { lf("layout cancelled"); for (int i = 0; i < pageCount; i++) { delete pages[i]; } pageCount = 0; delete pd; // send a 'finished' message so that the thread object gets deleted SendPagesIfNecessary(true, true, fromBeginning); delete formatter; return true; } pages[pageCount++] = pd; ++totalPageCount; // we send first 5 pages one by one and the rest in batches to minimize user-visible // latency but also not overload ui thread SendPagesIfNecessary(totalPageCount < 5, false, fromBeginning); CrashIf(pageCount >= dimof(pages)); } // this is the last message only if we're laying out from the beginning bool finished = fromBeginning; SendPagesIfNecessary(true, finished, fromBeginning); //lf("Laying out took %.2f ms", t.GetTimeInMs()); delete formatter; return false; }
// layout pages from a given reparse point (beginning if nullptr) // returns true if layout thread was cancelled bool EbookFormattingThread::Format() { //lf("Started laying out ebook, reparseIdx=%d", reparseIdx); int totalPageCount = 0; formatterArgs->reparseIdx = 0; pagesAfterReparseIdx = 0; HtmlFormatter *formatter = doc.CreateFormatter(formatterArgs); for (HtmlPage *pd = formatter->Next(); pd; pd = formatter->Next()) { if (WasCancelRequested()) { //lf("layout cancelled"); for (int i = 0; i < pageCount; i++) { delete pages[i]; } pageCount = 0; delete pd; // send a 'finished' message so that the thread object gets deleted SendPagesIfNecessary(true, true /* finished */); delete formatter; return true; } pages[pageCount++] = pd; ++totalPageCount; if (pd->reparseIdx >= reparseIdx) { ++pagesAfterReparseIdx; } // force sending accumulated pages bool force = false; if (2 == pagesAfterReparseIdx) { force = true; //lf("EbookFormattingThread::Format: sending pages because pagesAfterReparseIdx == %d", pagesAfterReparseIdx); } SendPagesIfNecessary(force, false); CrashIf(pageCount >= dimof(pages)); } SendPagesIfNecessary(true, true /* finished */); delete formatter; return false; }