예제 #1
0
static void GetSortedFilePaths(Vec<const WCHAR *>& filePathsSortedOut, DisplayState *toIgnore=NULL)
{
    DisplayState *ds;
    for (size_t i = 0; (ds = gFileHistory.Get(i)) != NULL; i++) {
        if (ds->favorites->Count() > 0 && ds != toIgnore)
            filePathsSortedOut.Append(ds->filePath);
    }
    filePathsSortedOut.Sort(SortByBaseFileName);
}
예제 #2
0
static void GetSortedFilePaths(Favorites *favorites, Vec<TCHAR*>& filePathsSortedOut, FileFavs *toIgnore)
{
    for (size_t i = 0; i < favorites->favs.Count(); i++) {
        FileFavs *f = favorites->favs.At(i);
        if (f != toIgnore)
            filePathsSortedOut.Append(f->filePath);
    }
    filePathsSortedOut.Sort(SortByBaseFileName);
}
예제 #3
0
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;
}
예제 #4
0
// returns a shallow copy of the file history list, sorted
// by open count (which has a pre-multiplied recency factor)
// and with all missing states filtered out
// caller needs to delete the result (but not the contained states)
void FileHistory::GetFrequencyOrder(Vec<DisplayState*>& list) {
    CrashIf(list.size() > 0);
    size_t i = 0;
    for (DisplayState* ds : *states) {
        ds->index = i++;
        if (!ds->isMissing || ds->isPinned)
            list.Append(ds);
    }
    list.Sort(cmpOpenCount);
}
예제 #5
0
bool CbxEngineImpl::LoadCbrFile(const WCHAR *file)
{
    if (!file)
        return false;
    fileName = str::Dup(file);
    fileExt = L".cbr";

    RAROpenArchiveDataEx  arcData = { 0 };
    arcData.ArcNameW = (WCHAR *)file;
    arcData.OpenMode = RAR_OM_EXTRACT;

    HANDLE hArc = RAROpenArchiveEx(&arcData);
    if (!hArc || arcData.OpenResult != 0)
        return false;

    // UnRAR does not seem to support extracting a single file by name,
    // so lazy image loading doesn't seem possible

    Vec<ImagesPage *> found;
    for (;;) {
        RARHeaderDataEx rarHeader;
        int res = RARReadHeaderEx(hArc, &rarHeader);
        if (0 != res)
            break;

        const WCHAR *fileName = rarHeader.FileNameW;
        if (ImageEngine::IsSupportedFile(fileName)) {
            ImagesPage *page = LoadCurrentCbrPage(hArc, rarHeader);
            if (page)
                found.Append(page);
        }
        else if (str::EqI(fileName, L"ComicInfo.xml")) {
            ScopedMem<char> xmlData(LoadCurrentCbrFile(hArc, rarHeader, NULL));
            if (xmlData)
                ParseComicInfoXml(xmlData);
        }
        else
            RARProcessFile(hArc, RAR_SKIP, NULL, NULL);

    }
    RARCloseArchive(hArc);

    if (found.Count() == 0)
        return false;
    found.Sort(ImagesPage::cmpPageByName);

    for (size_t i = 0; i < found.Count(); i++) {
        pages.Append(found.At(i)->bmp);
        found.At(i)->bmp = NULL;
    }
    mediaboxes.AppendBlanks(pages.Count());

    DeleteVecMembers(found);
    return true;
}
예제 #6
0
bool CbxEngineImpl::FinishLoadingCbz()
{
    fileExt = L".cbz";

    Vec<const WCHAR *> allFileNames;

    for (size_t idx = 0; idx < cbzFile->GetFileCount(); idx++) {
        const WCHAR *fileName = cbzFile->GetFileName(idx);
        // bail, if we accidentally try to load an XPS file
        if (fileName && str::StartsWith(fileName, L"_rels/.rels"))
            return false;
        if (fileName && ImageEngine::IsSupportedFile(fileName) &&
            // OS X occasionally leaves metadata with image extensions
            !str::StartsWith(path::GetBaseName(fileName), L".")) {
            allFileNames.Append(fileName);
        }
        else {
            allFileNames.Append(NULL);
        }
    }
    assert(allFileNames.Count() == cbzFile->GetFileCount());

    ScopedMem<char> metadata(cbzFile->GetFileData(L"ComicInfo.xml"));
    if (metadata)
        ParseComicInfoXml(metadata);
    metadata.Set(cbzFile->GetComment());
    if (metadata)
        json::Parse(metadata, this);

    Vec<const WCHAR *> pageFileNames;
    for (const WCHAR **fn = allFileNames.IterStart(); fn; fn = allFileNames.IterNext()) {
        if (*fn)
            pageFileNames.Append(*fn);
    }
    pageFileNames.Sort(cmpAscii);
    for (const WCHAR **fn = pageFileNames.IterStart(); fn; fn = pageFileNames.IterNext()) {
        fileIdxs.Append(allFileNames.Find(*fn));
    }
    assert(pageFileNames.Count() == fileIdxs.Count());
    if (fileIdxs.Count() == 0)
        return false;

    pages.AppendBlanks(fileIdxs.Count());
    mediaboxes.AppendBlanks(fileIdxs.Count());

    return true;
}
예제 #7
0
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;
}