Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1695860
  • 博文数量: 584
  • 博客积分: 13857
  • 博客等级: 上将
  • 技术积分: 11883
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-16 09:34

分类: LINUX

2010-10-25 22:53:06

浅析minigui中GDI接口BeginPaint

使用如下3个语句,绘制数据到lcd上.
RotateBitmap(rotate->hdc, &(rotate->foreground), rotate->forex, rotate->forey, rotate->angle * 64);
hdc = BeginPaint(hwnd); // 获取的pdc->cur_dst该cur_dst将直接指向framebuffer,进而对cur_dst的赋值数据将
// 直接反应到lcd屏幕上.
BitBlt(rotate->hdc, 0, 0, 0, 0, hdc, 0, 0, 0);
// 将上面经过n多计算之后rotate->hdc矩形区中的数据,剪切之后,按需依次复制到hdc->cur_dst对应的 framebuffer地址中,
// 进而一次性显示到lcd屏幕上,这样BitBlt里面只是进行剪切计算和数据搬移工作,没有任何rotate图像旋转计算了,
// rotate图像旋转计算的最后结果数据都已经存放到rotate->hdc这个由malloc申请的内存缓冲区中了,
// 所以BitBlt将只是作数据搬移操作,将rotate->hdc中旋转计算好的数据直接搬移到cur_dst指向的framebuffer中,
// 进而不带闪烁的立即显示到lcd屏幕上[luther.gliethttp]
EndPaint(hwnd, hdc);

看看源 码是怎么做到的
BeginPaint
hdc = GetClientDC (hWnd); // 获取一个client DC,该dc的pixel
#define DCSLOTNUMBER        16
HDC GUIAPI GetClientDC (HWND hWnd)
{
    int i;

    LOCK (&dcslot);
    for (i = 0; i < DCSLOTNUMBER; i++) { // 最多16个
        if (!DCSlot[i].inuse) {
            DCSlot[i].inuse = TRUE;
            DCSlot[i].DataType = TYPE_HDC;
            DCSlot[i].DCType   = TYPE_GENDC;
            DCSlot[i].surface = __gal_screen; // 使用lcd全屏surface : __gal_screen [luther.gliethttp]
// __gal_screen的创建位于industrialsample/libminigui-1.6.10/src/newgal/newgal.c中
// __gal_screen = GAL_SetVideoMode (w, h, depth, GAL_HWPALETTE)); 这时
// __gal_screen->pixels = mapped_mem+mapped_offset;经过mmap的framebuffer首地址了,
// 对于QVFB来说__gal_screen->pixels = this->hidden->shmrgn + this->hidden->hdr->dataoffset;
// 同样是以共享内存方式工作qvfb应用程序显示区的首地址[luther.gliethttp]
            break;
        }
    }
    UNLOCK (&dcslot);

    if (i >= DCSLOTNUMBER) // 如果超过了,那么返回全屏幕对应的HDC_SCREEN [lutehr.gliethttp]
        return HDC_SCREEN;

    dc_InitDC (DCSlot + i, hWnd, TRUE); // 初始化该hdc
    return (HDC) (DCSlot + i);
}

static void dc_InitDC (PDC pdc, HWND hWnd, BOOL bIsClient)
{
    PCONTROL pCtrl;

    pdc->hwnd = hWnd;

    pdc->bkcolor = GAL_MapRGB (pdc->surface->format, 0xFF, 0xFF, 0xFF);
    pdc->bkmode = 0;

    pdc->pencolor = GAL_MapRGB (pdc->surface->format, 0x00, 0x00, 0x00);
    pdc->brushcolor = GAL_MapRGB (pdc->surface->format, 0xFF, 0xFF, 0xFF);

    pdc->textcolor = GAL_MapRGB (pdc->surface->format, 0x00, 0x00, 0x00);
    if (!(pdc->pLogFont = GetWindowFont (hWnd)))
        pdc->pLogFont = GetSystemFont (SYSLOGFONT_WCHAR_DEF);
    pdc->tabstop = 8;
    pdc->cExtra = pdc->alExtra = pdc->blExtra = 0;

    pdc->mapmode = MM_TEXT;
    pdc->ViewOrig.x = pdc->ViewOrig.y = 0;
    pdc->ViewExtent.x = pdc->ViewExtent.y = 1;
    pdc->WindowOrig.x = pdc->WindowOrig.y = 0;
    pdc->WindowExtent.x = pdc->WindowExtent.y = 1;

#ifdef _ADV_2DAPI
    pdc->pen_type = PT_SOLID;
    pdc->pen_cap_style = PT_CAP_BUTT;
    pdc->pen_join_style = PT_JOIN_MITER;
    pdc->pen_width = 0;
    pdc->dash_offset = 0;
    pdc->dash_list = NULL;
    pdc->dash_list_len = 0;

    pdc->brush_type = BT_SOLID;
    pdc->brush_orig.x = pdc->brush_orig.y = 0;
    pdc->brush_tile = NULL;
    pdc->brush_stipple = NULL;
#endif

    /* Assume that the local clip region is empty. */
    /* Get global clip region info and generate effective clip region. */
    if (dc_IsGeneralDC (pdc)) {
        // 执行如下代码
        RECT minimal;

        pdc->pGCRInfo = GetGCRgnInfo (hWnd);
        LOCK_GCRINFO (pdc);

        pdc->oldage = pdc->pGCRInfo->age;
        ClipRgnCopy (&pdc->ecrgn, &pdc->pGCRInfo->crgn);

        pdc->bIsClient = bIsClient;
        if (bIsClient)
            WndClientRect (pdc->hwnd, &pdc->DevRC);
        else
            WndRect (pdc->hwnd, &pdc->DevRC);

        minimal = pdc->DevRC;

        pCtrl = Control (pdc->hwnd);
        if (pCtrl && !(pCtrl->dwExStyle & WS_EX_CTRLASMAINWIN))
            RestrictControlECRGN (&minimal, pCtrl);

        IntersectClipRect (&pdc->ecrgn, &minimal);

        UNLOCK_GCRINFO (pdc);
    }

    /* context info and raster operations. */
    pdc->CurPenPos.x = pdc->CurTextPos.x = 0;
    pdc->CurPenPos.y = pdc->CurTextPos.y = 0;

    pdc->rop = ROP_SET;
    pdc->step = 1;
    pdc->set_pixel =
        set_pixel_ops [pdc->rop][pdc->surface->format->BytesPerPixel - 1];
    pdc->draw_hline =
        draw_hline_ops [pdc->rop][pdc->surface->format->BytesPerPixel - 1];
    pdc->put_hline =
        put_hline_ops [pdc->rop][pdc->surface->format->BytesPerPixel - 1];

    pdc->cur_dst = (BYTE*)pdc->surface->pixels // pdc->DevRC.top为绝对坐标值,
    // 根据绝对坐标值,计算该pdc左上角坐标(left,top)对应的framebuffer
    // 区起始地址[luther.gliethttp][这个很关键,因为这就表示以后对该pdc->cur_dst的所有赋值操作,
    // 都将直接反应到framebuffer中,进而直接反应到lcd屏幕上][lutehr.gliethttp]
            + pdc->surface->pitch * pdc->DevRC.top
            + pdc->surface->format->BytesPerPixel * pdc->DevRC.left;

    pdc->move_to = move_to_ops [pdc->surface->format->BytesPerPixel - 1];
    pdc->step_x = step_x_ops [pdc->surface->format->BytesPerPixel - 1];

    memset (pdc->gray_pixels, 0, sizeof (pdc->gray_pixels));
    memset (pdc->filter_pixels, 0, sizeof (pdc->filter_pixels));
    pdc->alpha_pixel_format = NULL;
}
阅读(1916) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~