UINT RenderCache::Paint(HDC hdc, RectI bounds, DisplayModel *dm, int pageNo, PageInfo *pageInfo, bool *renderOutOfDateCue) { assert(pageInfo->shown && 0.0 != pageInfo->visibleRatio); USHORT tileRes = GetTileRes(dm, pageNo); bool renderedReplacement; UINT renderTime = RENDER_DELAY_UNDEFINED, renderTimeMin = renderTime = RENDER_DELAY_UNDEFINED; for (int res = 0; res <= tileRes; res++) { renderedReplacement = false; renderTime = PaintTiles(hdc, bounds, dm, pageNo, pageInfo->pageOnScreen, res, res == tileRes, renderOutOfDateCue, &renderedReplacement); renderTimeMin = min(renderTime, renderTimeMin); } #ifdef CONSERVE_MEMORY if (0 == renderTime && !renderedReplacement) { // free tiles with different resolution TilePosition tile = { tileRes, -1, 0 }; FreePage(dm, pageNo, &tile); } #endif return renderTimeMin; }
UINT RenderCache::Paint(HDC hdc, RectI bounds, DisplayModel *dm, int pageNo, PageInfo *pageInfo, bool *renderOutOfDateCue) { assert(pageInfo->shown && 0.0 != pageInfo->visibleRatio); int rotation = dm->Rotation(); float zoom = dm->ZoomReal(); USHORT targetRes = GetTileRes(dm, pageNo); USHORT maxRes = GetMaxTileRes(dm, pageNo, rotation); if (maxRes < targetRes) maxRes = targetRes; Vec<TilePosition> queue; queue.Append(TilePosition(0, 0, 0)); UINT renderDelayMin = RENDER_DELAY_UNDEFINED; bool neededScaling = false; while (queue.Count() > 0) { TilePosition tile = queue.At(0); queue.RemoveAt(0); RectI tileOnScreen = GetTileOnScreen(dm->engine, pageNo, rotation, zoom, tile, pageInfo->pageOnScreen); tileOnScreen = pageInfo->pageOnScreen.Intersect(tileOnScreen); RectI isect = bounds.Intersect(tileOnScreen); if (isect.IsEmpty()) continue; bool isTargetRes = tile.res == targetRes; UINT renderDelay = PaintTile(hdc, isect, dm, pageNo, tile, tileOnScreen, isTargetRes, renderOutOfDateCue, isTargetRes ? &neededScaling : NULL); if (!(isTargetRes && 0 == renderDelay) && tile.res < maxRes) { queue.Append(TilePosition(tile.res + 1, tile.row * 2, tile.col * 2)); queue.Append(TilePosition(tile.res + 1, tile.row * 2, tile.col * 2 + 1)); queue.Append(TilePosition(tile.res + 1, tile.row * 2 + 1, tile.col * 2)); queue.Append(TilePosition(tile.res + 1, tile.row * 2 + 1, tile.col * 2 + 1)); } if (isTargetRes && renderDelay > 0) neededScaling = true; renderDelayMin = min(renderDelay, renderDelayMin); // paint tiles from left to right from top to bottom if (tile.res > 0 && queue.Count() > 0 && tile.res < queue.At(0).res) queue.Sort(cmpTilePosition); } #ifdef CONSERVE_MEMORY if (!neededScaling) { if (renderOutOfDateCue) *renderOutOfDateCue = false; // free tiles with different resolution TilePosition tile(targetRes, (USHORT)-1, 0); FreePage(dm, pageNo, &tile); } FreeNotVisible(); #endif return renderDelayMin; }
void RenderCache::Render(DisplayModel *dm, int pageNo, RenderingCallback *callback) { TilePosition tile = { GetTileRes(dm, pageNo), 0, 0 }; Render(dm, pageNo, tile, true, callback); // render both tiles of the first row when splitting a page in four // (which always happens on larger displays for Fit Width) if (tile.res == 1 && !IsRenderQueueFull()) { tile.col = 1; Render(dm, pageNo, tile, false); } }
void RenderCache::RequestRendering(DisplayModel* dm, int pageNo) { TilePosition tile(GetTileRes(dm, pageNo), 0, 0); // only honor the request if there's a good chance that the // rendered tile will actually be used if (tile.res > 1) return; RequestRendering(dm, pageNo, tile); // render both tiles of the first row when splitting a page in four // (which always happens on larger displays for Fit Width) if (tile.res == 1 && !IsRenderQueueFull()) { tile.col = 1; RequestRendering(dm, pageNo, tile, false); } }
UINT RenderCache::Paint(HDC hdc, RectI bounds, DisplayModel* dm, int pageNo, PageInfo* pageInfo, bool* renderOutOfDateCue) { AssertCrash(pageInfo->shown && 0.0 != pageInfo->visibleRatio); if (!dm->ShouldCacheRendering(pageNo)) { int rotation = dm->GetRotation(); float zoom = dm->GetZoomReal(pageNo); bounds = pageInfo->pageOnScreen.Intersect(bounds); RectD area = bounds.Convert<double>(); area.Offset(-pageInfo->pageOnScreen.x, -pageInfo->pageOnScreen.y); area = dm->GetEngine()->Transform(area, pageNo, zoom, rotation, true); RenderedBitmap* bmp = dm->GetEngine()->RenderBitmap(pageNo, zoom, rotation, &area); bool success = bmp && bmp->GetBitmap() && bmp->StretchDIBits(hdc, bounds); delete bmp; return success ? 0 : RENDER_DELAY_FAILED; } int rotation = dm->GetRotation(); float zoom = dm->GetZoomReal(); USHORT targetRes = GetTileRes(dm, pageNo); USHORT maxRes = GetMaxTileRes(dm, pageNo, rotation); if (maxRes < targetRes) maxRes = targetRes; Vec<TilePosition> queue; queue.Append(TilePosition(0, 0, 0)); UINT renderDelayMin = RENDER_DELAY_UNDEFINED; bool neededScaling = false; while (queue.size() > 0) { TilePosition tile = queue.PopAt(0); RectI tileOnScreen = GetTileOnScreen(dm->GetEngine(), pageNo, rotation, zoom, tile, pageInfo->pageOnScreen); if (tileOnScreen.IsEmpty()) { // display an error message when only empty tiles should be drawn (i.e. on page loading errors) renderDelayMin = std::min(RENDER_DELAY_FAILED, renderDelayMin); continue; } tileOnScreen = pageInfo->pageOnScreen.Intersect(tileOnScreen); RectI isect = bounds.Intersect(tileOnScreen); if (isect.IsEmpty()) continue; bool isTargetRes = tile.res == targetRes; UINT renderDelay = PaintTile(hdc, isect, dm, pageNo, tile, tileOnScreen, isTargetRes, renderOutOfDateCue, isTargetRes ? &neededScaling : nullptr); if (!(isTargetRes && 0 == renderDelay) && tile.res < maxRes) { queue.Append(TilePosition(tile.res + 1, tile.row * 2, tile.col * 2)); queue.Append(TilePosition(tile.res + 1, tile.row * 2, tile.col * 2 + 1)); queue.Append(TilePosition(tile.res + 1, tile.row * 2 + 1, tile.col * 2)); queue.Append(TilePosition(tile.res + 1, tile.row * 2 + 1, tile.col * 2 + 1)); } if (isTargetRes && renderDelay > 0) neededScaling = true; renderDelayMin = std::min(renderDelay, renderDelayMin); // paint tiles from left to right from top to bottom if (tile.res > 0 && queue.size() > 0 && tile.res < queue.at(0).res) queue.Sort(cmpTilePosition); } #ifdef CONSERVE_MEMORY if (!neededScaling) { if (renderOutOfDateCue) *renderOutOfDateCue = false; // free tiles with different resolution TilePosition tile(targetRes, (USHORT)-1, 0); FreePage(dm, pageNo, &tile); } FreeNotVisible(); #endif return renderDelayMin; }