⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 displaymodel.cc.svn-base

📁 SumatraPDF是一款小型开源的pdf阅读工具。虽然玲珑小巧(只有800多KB)
💻 SVN-BASE
📖 第 1 页 / 共 4 页
字号:
            freedSomething = true;
            BitmapCacheEntry_Free(gBitmapCache[i]);
            gBitmapCache[i] = NULL;
            --gBitmapCacheCount;
        }

        if (curPos != i)
            gBitmapCache[curPos] = gBitmapCache[i];

        if (!shouldFree)
            ++curPos;
    }
    UnlockCache();
    if (freedSomething)
        DBG_OUT("\n");
    return freedSomething;
}

void BitmapCache_Add(DisplayModel *dm, int pageNo, double zoomLevel, int rotation, 
    RenderedBitmap *bitmap, double renderTime) {
    assert(gBitmapCacheCount <= MAX_BITMAPS_CACHED);
    assert(dm);
    assert(validRotation(rotation));

    normalizeRotation(&rotation);
    DBG_OUT("BitmapCache_Add(pageNo=%d, zoomLevel=%.2f%%, rotation=%d)\n", pageNo, zoomLevel, rotation);
    LockCache();

    /* It's possible there still is a cached bitmap with different zoomLevel/rotation */
    BitmapCache_FreePage(dm, pageNo);

    if (gBitmapCacheCount >= MAX_BITMAPS_CACHED - 1) {
        /* TODO: find entry that is not visible and remove it from cache to
           make room for new entry */
        delete bitmap;
        goto UnlockAndExit;
    }
    BitmapCacheEntry* entry = (BitmapCacheEntry*)malloc(sizeof(BitmapCacheEntry));
    if (!entry) {
        delete bitmap;
        goto UnlockAndExit;
    }
    entry->dm = dm;
    entry->pageNo = pageNo;
    entry->zoomLevel = zoomLevel;
    entry->rotation = rotation;
    entry->bitmap = bitmap;
    entry->renderTime = renderTime;
    gBitmapCache[gBitmapCacheCount++] = entry;
UnlockAndExit:
    UnlockCache();
}

BitmapCacheEntry *BitmapCache_Find(DisplayModel *dm, int pageNo) {
    BitmapCacheEntry* entry;
    LockCache();
    for (int i = 0; i < gBitmapCacheCount; i++) {
        entry = gBitmapCache[i];
        if ( (dm == entry->dm) && (pageNo == entry->pageNo) ) {
             goto Exit;
        }
    }
    entry = NULL;
Exit:
    UnlockCache();
    return entry;
}

BitmapCacheEntry *BitmapCache_Find(DisplayModel *dm, int pageNo, double zoomLevel, int rotation) {
    BitmapCacheEntry *entry;
    normalizeRotation(&rotation);
    LockCache();
    for (int i = 0; i < gBitmapCacheCount; i++) {
        entry = gBitmapCache[i];
        if ( (dm == entry->dm) && (pageNo == entry->pageNo) && 
             (zoomLevel == entry->zoomLevel) && (rotation == entry->rotation)) {
             goto Exit;
        }
    }
    entry = NULL;
Exit:
    UnlockCache();
    return entry;
}

/* Return true if a bitmap for a page defined by <dm>, <pageNo>, <zoomLevel>
   and <rotation> exists in the cache */
bool BitmapCache_Exists(DisplayModel *dm, int pageNo, double zoomLevel, int rotation) {
    if (BitmapCache_Find(dm, pageNo, zoomLevel, rotation))
        return true;
    return false;
}

PdfSearchResult *DisplayModel::Find(PdfSearchDirection direction, wchar_t *text)
{
    showBusyCursor();

    bool forward = (direction == FIND_FORWARD);
    _pdfSearch->SetDirection(forward);
    if (text != NULL)
        bFoundText = _pdfSearch->FindFirst(currentPageNo(), text);
    else
        bFoundText = _pdfSearch->FindNext();

    if (bFoundText) {
        PdfSearchResult &rect = _pdfSearch->result;

        goToPage(rect.page, 0);
        MapResultRectToScreen(&rect);
        showNormalCursor();
        return &rect;
    }

    showNormalCursor();
    return NULL;
}

DisplayModel *DisplayModel_CreateFromFileName(
  const WCHAR *fileName,
  SizeD totalDrawAreaSize,
  int scrollbarXDy, int scrollbarYDx,
  DisplayMode displayMode, int startPage,
  WindowInfo *win, bool tryrepair)
{
    DisplayModel *    dm = NULL;

    dm = new DisplayModel(displayMode);
    if (!dm)
        goto Error;

    if (!dm->load(fileName, startPage, win, tryrepair))
        goto Error;

    dm->setScrollbarsSize(scrollbarXDy, scrollbarYDx);
    dm->setTotalDrawAreaSize(totalDrawAreaSize);

//    DBG_OUT("DisplayModel_CreateFromPageTree() pageCount = %d, startPage=%d, displayMode=%d\n",
//        dm->pageCount(), (int)dm->startPage, (int)displayMode);
    return dm;
Error:
    delete dm;
    return NULL;
}

bool DisplayModel::cvtUserToScreen(int pageNo, double *x, double *y)
{
    pdf_page *page = pdfEngine->getPdfPage(pageNo);
    double zoom = zoomReal();
    int rot = rotation();
    fz_point p;
    assert(page);
    if(!page)
        return false;

    normalizeRotation(&rot);
    zoom *= 0.01;

    p.x = *x;
    p.y = *y;

    fz_matrix ctm = pdfEngine->viewctm(page, zoom, rot);

    fz_point tp = fz_transformpoint(ctm, p);

    PdfPageInfo *pageInfo = getPageInfo(pageNo);

    rot += pageInfo->rotation;
    double vx = 0, vy = 0;
    if (rot == 90 || rot == 180)
        vx += pageInfo->currDx;
    if (rot == 180 || rot == 270)
        vy += pageInfo->currDy;

    *x = tp.x + 0.5 + pageInfo->screenX - pageInfo->bitmapX + vx;
    *y = tp.y + 0.5 + pageInfo->screenY - pageInfo->bitmapY + vy;
    return true;
}

bool DisplayModel::cvtScreenToUser(int *pageNo, double *x, double *y)
{
    double zoom = zoomReal();
    int rot = rotation();
    fz_point p;

    normalizeRotation(&rot);
    zoom *= 0.01;

    *pageNo = getPageNoByPoint(*x, *y);
    if (*pageNo == POINT_OUT_OF_PAGE) 
        return false;

    pdf_page *page = pdfEngine->getPdfPage(*pageNo);

    const PdfPageInfo *pageInfo = getPageInfo(*pageNo);

    p.x = *x - 0.5 - pageInfo->screenX + pageInfo->bitmapX;
    p.y = *y - 0.5 - pageInfo->screenY + pageInfo->bitmapY;

    fz_matrix ctm = pdfEngine->viewctm(page, zoom, rot);
    fz_matrix invCtm = fz_invertmatrix(ctm);

    fz_point tp = fz_transformpoint(invCtm, p);

    double vx = 0, vy = 0;
    if (rot == 90 || rot == 180)
        vy -= pageInfo->pageDy;
    if (rot == 180 || rot == 270)
        vx += pageInfo->pageDx;

    *x = tp.x + vx;
    *y = tp.y + vy;
    return true;
}

static void launch_url_a(const char *url)
{
    SHELLEXECUTEINFOA sei;

    ZeroMemory(&sei, sizeof(sei));
    sei.cbSize  = sizeof(sei);
    sei.fMask   = SEE_MASK_FLAG_NO_UI;
    sei.lpVerb  = "open";
    sei.lpFile  = url;
    sei.nShow   = SW_SHOWNORMAL;

    ShellExecuteExA(&sei);
}

void DisplayModel::handleLink2(pdf_link* link)
{
    if (PDF_LURI == link->kind)
    {
        char *uri = fz_tostrbuf(link->dest);
        if (!str_startswithi(uri, "http"))
        {
            /* unsupported uri type */
            return;
        }
        launch_url_a(uri);

    } else if (PDF_LGOTO == link->kind)
    {
        int page = pdfEngine->findPageNo(link->dest);
        if (page > 0) 
            goToPage(page, 0);
    }
}

void DisplayModel::handleLink(PdfLink *link)
{
    handleLink2(link->link);
}

void DisplayModel::goToTocLink(void *linktmp)
{
    if (!linktmp)
        return;

    pdf_link *link = (pdf_link*)linktmp;
    handleLink2(link);
}

void DisplayModel::goToNamedDest(const char *name)
{
    fz_obj *dest = pdfEngine->getNamedDest(name);
    if (!dest)
    {
        goToPage(1, 0);
        return;
    }
    int page = pdfEngine->findPageNo(dest);
    if (page > 0)
        goToPage(page, 0);
}

/* Given <region> (in user coordinates ) on page <pageNo>, copies text in that region
 * to <buf>. Returnes number of copied characters */
int DisplayModel::getTextInRegion(int pageNo, RectD *region, unsigned short *buf, int buflen)
{
    int             bxMin, bxMax, byMin, byMax;
    int             xMin, xMax, yMin, yMax;
    pdf_textline *  line, *ln;
    fz_error *      error;
    pdf_page *      page = pdfEngine->getPdfPage(pageNo);
    fz_tree *       tree = page->tree;
    double          rot = 0;
    double          zoom = 1;

    error = pdf_loadtextfromtree(&line, tree, fz_identity());
    if (error)
        return 0;

    xMin = (int)region->x;
    xMax = xMin + (int)region->dx;
    yMin = (int)region->y;
    yMax = yMin + (int)region->dy;

    int p = 0;
    for (ln = line; ln; ln = ln->next) {
        int oldP = p;
        for (int i = 0; i < ln->len; i++) {
            bxMin = ln->text[i].bbox.x0;
            bxMax = ln->text[i].bbox.x1;
            byMin = ln->text[i].bbox.y0;
            byMax = ln->text[i].bbox.y1;
            int c = ln->text[i].c;
            if (c < 32)
                c = '?';
            if (bxMax >= xMin && bxMin <= xMax && byMax >= yMin && byMin <= yMax 
                    && p < buflen) {
                buf[p++] = c;
                //DBG_OUT("Char: %c : %d; ushort: %hu\n", (char)c, (int)c, (unsigned short)c);
                //DBG_OUT("Found char: %c : %hu; real %c : %hu\n", c, (unsigned short)(unsigned char) c, ln->text[i].c, ln->text[i].c);
            }
        }

        if (p > oldP && p < buflen - 1) {
#ifdef WIN32
            buf[p++] = '\r'; buf[p++] = 10;
            //DBG_OUT("Char: %c : %d; ushort: %hu\n", (char)buf[p], (int)(unsigned char)buf[p], buf[p]);
#else
            buf[p++] = '\n';
#endif
        }
    }

    pdf_droptextline(line);

    return p;
}

void DisplayModel::MapResultRectToScreen(PdfSearchResult *rect)
{
    PdfPageInfo *pageInfo = getPageInfo(rect->page);
    pdf_page *page = pdfEngine->getPdfPage(rect->page);
    if(!page)
        return;
    int rot = rotation();
    normalizeRotation (&rot);

    double vx = pageInfo->screenX - pageInfo->bitmapX,
           vy = pageInfo->screenY - pageInfo->bitmapY;
    if (rot == 90 || rot == 180)
        vx += pageInfo->currDx;
    if (rot == 180 || rot == 270)
        vy += pageInfo->currDy;

    double left = rect->left, top = rect->top, right = rect->right, bottom = rect->bottom;
    fz_matrix ctm = pdfEngine->viewctm(page, zoomReal() * 0.01, rot);
    fz_point tp, p1 = {left, top}, p2 = {right, bottom};

    tp = fz_transformpoint(ctm, p1);
    left = tp.x - 0.5 + vx;
    top = tp.y - 0.5 + vy;

    tp = fz_transformpoint(ctm, p2);
    right = tp.x + 0.5 + vx;
    bottom = tp.y + 0.5 + vy;
    
    if (top > bottom) {
        double tmp = top;
        top = bottom;
        bottom = tmp;
    }

    rect->left = (int)floor(left);
    rect->top = (int)floor(top);
    rect->right = (int)ceil(right) + 5;
    rect->bottom = (int)ceil(bottom) + 5;

    int sx = 0, sy = 0;
    if (rect->bottom > pageInfo->screenY + pageInfo->bitmapY + pageInfo->bitmapDy)
        sy = rect->bottom - pageInfo->screenY - pageInfo->bitmapY - pageInfo->bitmapDy;

    if (rect->left < pageInfo->screenX + pageInfo->bitmapX) {
        sx = rect->left - pageInfo->screenX - pageInfo->bitmapX - 5;
        if (sx + pageInfo->screenX + pageInfo->bitmapX < 0)
            sx = -(pageInfo->screenX + pageInfo->bitmapX);
    }
    else
    if (rect->right > pageInfo->screenX + pageInfo->bitmapDx) {
        sx = rect->right - (pageInfo->screenX + pageInfo->bitmapDx) + 5;
    }

    if (sx != 0) {
        scrollXBy(sx);
        rect->left -= sx;
        rect->right -= sx;
    }

    if (sy > 0) {
        scrollYBy(sy, false);
        rect->top -= sy;
        rect->bottom -= sy;
    }
}

void DisplayModel::rebuildLinks()
{
    int count = pdfEngine->linkCount();
    assert(count > _linksCount);
    free(_links);
    _links = (PdfLink*)malloc(count * sizeof(PdfLink));
    _linksCount = count;
    pdfEngine->fillPdfLinks(_links, _linksCount);
    recalcLinksCanvasPos();
}

int DisplayModel::getLinkCount()
{
    /* TODO: let's hope it's not too expensive. An alternative would be
       to update link count only when it could have changed i.e. after
       loading a page */
    int count = pdfEngine->linkCount();
    if (count != _linksCount)
    {
        assert(count > _linksCount);
        rebuildLinks();
    }
    return count;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -