📄 dx_viewport.cpp
字号:
return; } else if(is_empty_region(hrgn)) { // nothing to paint viewport_logger->trace("%s: Region is empty for transition", tr->get_type_str().c_str()); DeleteObject((HGDIOBJ)hrgn); return; } IDirectDrawSurface* surf = create_surface(); if(!tr->is_outtrans()) copy_bgd_to(surf, dst_rc); draw(src, src_rc, dst_rc, keysrc, surf); OffsetRgn(hrgn, dst_rc.left(), dst_rc.top()); draw_to_bgd(surf, dst_rc, hrgn); release_surface(surf); DeleteObject((HGDIOBJ)hrgn);}void gui::dx::viewport::draw(IDirectDrawSurface* src, const lib::rect& src_rc, const lib::rect& dst_rc, bool keysrc, IDirectDrawSurface* dstview) { if(!dstview || !src) return; RECT srcRC = {src_rc.left(), src_rc.top(), src_rc.right(), src_rc.bottom()}; RECT dstRC = {dst_rc.left(), dst_rc.top(), dst_rc.right(), dst_rc.bottom()}; // Verify: // 1. Src within surf RECT surfRC; set_rect(src, &surfRC); if(!IntersectRect(&srcRC, &srcRC, &surfRC) || IsRectEmpty(&srcRC)) return; // 2. Dest within viewport RECT vrc = {0, 0, m_width, m_height}; if(!IntersectRect(&dstRC, &dstRC, &vrc) || IsRectEmpty(&dstRC)) return; DWORD flags = DDBLT_WAIT; if(keysrc) flags |= DDBLT_KEYSRC; HRESULT hr = dstview->Blt(&dstRC, src, &srcRC, flags, NULL); if (FAILED(hr)) { seterror(":viewport::clear/DirectDrawSurface::Blt()", hr); viewport_logger->trace("Blt %s --> %s failed", repr(src_rc).c_str(), repr(dst_rc).c_str()); }}// Paints the provided stringvoid gui::dx::viewport::draw(const std::basic_string<text_char>& text, const lib::rect& rc, lib::color_t clr) { if(!m_surface || text.empty()) return; HDC hdc; HRESULT hr = m_surface->GetDC(&hdc); if (FAILED(hr)) { seterror("DirectDrawSurface::GetDC()", hr); return; } SetBkMode(hdc, TRANSPARENT); COLORREF crTextColor = (clr == CLR_INVALID)?::GetSysColor(COLOR_WINDOWTEXT):clr; ::SetTextColor(hdc, crTextColor); RECT dstRC = {rc.left(), rc.top(), rc.right(), rc.bottom()}; UINT uFormat = DT_CENTER | DT_WORDBREAK; int res = ::DrawText(hdc, text.c_str(), int(text.length()), &dstRC, uFormat); if(res == 0) win_report_last_error("DrawText()"); m_surface->ReleaseDC(hdc);}// Frames the provided rectvoid gui::dx::viewport::frame_rect(const lib::rect& rc, lib::color_t clr) { if(!m_surface) return; HDC hdc; HRESULT hr = m_surface->GetDC(&hdc); if (FAILED(hr)) { seterror("DirectDrawSurface::GetDC()", hr); return; } RECT RC = {rc.left(), rc.top(), rc.right(), rc.bottom()}; HBRUSH hbr = CreateSolidBrush(clr); if(FrameRect(hdc, &RC, hbr) == 0) win_report_last_error("FrameRect()"); DeleteObject((HGDIOBJ) hbr); m_surface->ReleaseDC(hdc);}// Helper, that returns the size of a DD surface // staticlib::size gui::dx::viewport::get_size(IDirectDrawSurface* p) { assert(p); DDSURFACEDESC desc; ZeroMemory(&desc, sizeof(desc)); desc.dwSize = sizeof(desc); desc.dwFlags = DDSD_WIDTH | DDSD_HEIGHT; HRESULT hr = p->GetSurfaceDesc(&desc); assert(SUCCEEDED(hr)); return lib::size(desc.dwWidth, desc.dwHeight);}// Draw the src_rc of the DD surface to the back buffer and destination rectanglevoid gui::dx::viewport::blit(IDirectDrawSurface* src, const lib::rect& src_rc, IDirectDrawSurface* dst, const lib::rect& dst_rc) { RECT srcRC = {src_rc.left(), src_rc.top(), src_rc.right(), src_rc.bottom()}; RECT dstRC = {dst_rc.left(), dst_rc.top(), dst_rc.right(), dst_rc.bottom()}; // Verify: // 1. Src within surf RECT srcSurfRC; set_rect(src, &srcSurfRC); if(!IntersectRect(&srcRC, &srcRC, &srcSurfRC) || IsRectEmpty(&srcRC)) return; // 2. Dst within surf RECT dstSurfRC; set_rect(dst, &dstSurfRC); if(!IntersectRect(&dstRC, &dstRC, &dstSurfRC) || IsRectEmpty(&dstRC)) return; DWORD flags = DDBLT_WAIT; HRESULT hr = dst->Blt(&dstRC, src, &srcRC, flags, NULL); if (FAILED(hr)) { seterror("viewport::blit/DirectDrawSurface::Blt()", hr); viewport_logger->trace("Blt %s --> %s failed", repr(src_rc).c_str(), repr(dst_rc).c_str()); }}// Copies to the DD surface the back buffer within the from rectvoid gui::dx::viewport::rdraw(IDirectDrawSurface* dst, const lib::rect& from_rc) { if(!m_surface || !dst) return; DWORD flags = DDBLT_WAIT; // Set srcRC to surf rect RECT surfRC; set_rect(dst, &surfRC); RECT fromRC = {from_rc.left(), from_rc.top(), from_rc.right(), from_rc.bottom()}; // Verify: // Dest within viewport RECT vrc = {0, 0, m_width, m_height}; if(!IntersectRect(&fromRC, &fromRC, &vrc) || IsRectEmpty(&fromRC)) return; HRESULT hr = dst->Blt(&surfRC, m_surface, &fromRC, flags, NULL); if (FAILED(hr)) { seterror("viewport::rdraw/DirectDrawSurface::Blt()", hr); }}void gui::dx::viewport::copy_bgd_to(IDirectDrawSurface* surf, const lib::rect& rc) { if(!m_surface || !surf) return; DWORD flags = DDBLT_WAIT; RECT RC = {rc.left(), rc.top(), rc.right(), rc.bottom()}; RECT vrc = {0, 0, m_width, m_height}; if(!IntersectRect(&RC, &RC, &vrc) || IsRectEmpty(&RC)) return; HRESULT hr = surf->Blt(&RC, m_surface, &RC, flags, NULL); if (FAILED(hr)) { seterror("viewport::copy/DirectDrawSurface::Blt()", hr); }}void gui::dx::viewport::draw_to_bgd(IDirectDrawSurface* surf, const lib::rect& rc, HRGN hrgn) { if(!m_surface) return; DWORD flags = DDBLT_WAIT; RECT RC = {rc.left(), rc.top(), rc.right(), rc.bottom()}; RECT vrc = {0, 0, m_width, m_height}; if(!IntersectRect(&RC, &RC, &vrc) || IsRectEmpty(&RC)) return; HDC hdc; HRESULT hr = m_surface->GetDC(&hdc); if (FAILED(hr)) { seterror("DirectDrawSurface::GetDC()", hr); return; } HDC hsurfdc; hr = surf->GetDC(&hsurfdc); if(FAILED(hr)) { m_surface->ReleaseDC(hdc); seterror("DirectDrawSurface::GetDC()", hr); return; } if(hrgn) SelectClipRgn(hdc, hrgn); int w = RC.right - RC.left; int h = RC.bottom - RC.top; BOOL res = BitBlt(hdc, RC.left, RC.top, w, h, hsurfdc, RC.left, RC.top, SRCCOPY); if(!res) win_report_last_error("BitBlt"); m_surface->ReleaseDC(hdc); surf->ReleaseDC(hsurfdc);}////////////////////////// Internal pixel format related functionsuint16 gui::dx::viewport::low_bit_pos(uint32 dword) { uint32 test = 1; for(uint16 i=0;i<32;i++){ if(dword & test) return i; test <<= 1; } return 0;} uint16 gui::dx::viewport::high_bit_pos(uint32 dword) { uint32 test = 1; test <<= 31; for(uint16 i=0;i<32;i++){ if ( dword & test ) return (uint16)(31-i); test >>= 1; } return 0;} void gui::dx::viewport::get_pixel_format() { if(!m_primary_surface) return; DDPIXELFORMAT format; memset(&format, 0, sizeof(format)); format.dwSize = sizeof(format); HRESULT hr = m_primary_surface->GetPixelFormat(&format); if (FAILED(hr)){ seterror("DirectDrawSurface::GetPixelFormat()", hr); return; } bits_size = format.dwRGBBitCount; //viewport_logger->trace("bits_size: %u", bits_size); lo_red_bit = low_bit_pos( format.dwRBitMask ); uint16 hi_red_bit = high_bit_pos( format.dwRBitMask ); red_bits = (uint16)(hi_red_bit-lo_red_bit+1); lo_green_bit = low_bit_pos( format.dwGBitMask ); uint16 hi_green_bit = high_bit_pos(format.dwGBitMask); green_bits=(uint16)(hi_green_bit-lo_green_bit+1); lo_blue_bit = low_bit_pos( format.dwBBitMask ); uint16 hi_blue_bit = high_bit_pos(format.dwBBitMask); blue_bits=(uint16)(hi_blue_bit-lo_blue_bit+1);}// Converts a lib::color_t to a DD coloruint32 gui::dx::viewport::convert(lib::color_t color) { return convert(lib::redc(color), lib::greenc(color), lib::bluec(color));}// Converts the RGB tuple to a DD coloruint32 gui::dx::viewport::convert(BYTE r, BYTE g, BYTE b) { uint32 ddcolor = 0; if(bits_size == 8){ // find from palette return 0; } else if(bits_size == 16) { int rs = 8 - red_bits; int gs = 8 - green_bits; int bs = 8 - blue_bits; ddcolor = ((r >> rs) << lo_red_bit) | ((g>>gs) << lo_green_bit) | ((b>>bs) << lo_blue_bit); } else if (bits_size==24 || bits_size==32){ ddcolor = (r << lo_red_bit) | (g << lo_green_bit) | (b << lo_blue_bit); } return ddcolor;}// Internal function// Converts the provided rect to OS screen coordinatesRECT* gui::dx::viewport::to_screen_rc_ptr(RECT& r) { POINT pt = {r.left, r.top}; int w = r.right - r.left; int h = r.bottom - r.top; ClientToScreen(m_hwnd, &pt); r.left = pt.x; r.top = pt.y; r.right = pt.x + w; r.bottom = pt.y + h; return &r;}__forceinline int blend(int w, int c1, int c2) {return (c1==c2)?c1:(c1 + w*(c2-c1)/256); }HRESULT gui::dx::viewport::blt_blend32(const lib::rect& rc, double progress, IDirectDrawSurface *surf1, IDirectDrawSurface *surf2) { DDSURFACEDESC desc1, desc2; ZeroMemory(&desc1, sizeof(desc1)); desc1.dwSize = sizeof(desc1); ZeroMemory(&desc2, sizeof(desc2)); desc2.dwSize = sizeof(desc2); HRESULT hr = surf1->Lock(0, &desc1, DDLOCK_WAIT | DDLOCK_READONLY, 0); if(hr!=DD_OK) return hr; hr = surf2->Lock(0, &desc2, DDLOCK_WAIT, 0); if(hr != DD_OK) { surf1->Unlock(0); return hr; } lib::rect rcv(lib::point(0,0), lib::size(m_width,m_height)); lib::rect rcc = rc; rcc &= rcv; int begin_row = rcc.bottom(); int end_row = rcc.top(); int begin_col = rcc.left(); int end_col = rcc.right(); int weight = int(progress*256); for(int row = begin_row-1;row>=end_row;row--) { RGBQUAD* px1 = (RGBQUAD*)((BYTE*)desc1.lpSurface+row*desc1.lPitch); RGBQUAD* px2 = (RGBQUAD*)((BYTE*)desc2.lpSurface+row*desc2.lPitch); px1 += begin_col; px2 += begin_col; for(int col=begin_col;col<end_col;col++, px1++, px2++) { px2->rgbRed = (BYTE)blend(weight, px2->rgbRed, px1->rgbRed); px2->rgbGreen = (BYTE)blend(weight, px2->rgbGreen, px1->rgbGreen); px2->rgbBlue = (BYTE)blend(weight, px2->rgbBlue, px1->rgbBlue); } } surf1->Unlock(0); surf2->Unlock(0); return hr;}HRESULT gui::dx::viewport::blt_blend24(const lib::rect& rc, double progress, IDirectDrawSurface *surf1, IDirectDrawSurface *surf2) { DDSURFACEDESC desc1, desc2; ZeroMemory(&desc1, sizeof(desc1)); desc1.dwSize = sizeof(desc1); ZeroMemory(&desc2, sizeof(desc2)); desc2.dwSize = sizeof(desc2); HRESULT hr = surf1->Lock(0, &desc1, DDLOCK_WAIT | DDLOCK_READONLY, 0); if(hr!=DD_OK) return hr; hr = surf2->Lock(0, &desc2, DDLOCK_WAIT, 0); if(hr != DD_OK) { surf1->Unlock(0); return hr; } lib::rect rcv(lib::point(0,0), lib::size(m_width,m_height)); lib::rect rcc = rc; rcc &= rcv; int begin_row = rcc.bottom(); int end_row = rcc.top(); int begin_col = rcc.left(); int end_col = rcc.right(); int weight = int(progress*256); for(int row = begin_row-1;row>=end_row;row--) { RGBTRIPLE* px1 = (RGBTRIPLE*)((BYTE*)desc1.lpSurface+row*desc1.lPitch); RGBTRIPLE* px2 = (RGBTRIPLE*)((BYTE*)desc2.lpSurface+row*desc2.lPitch); px1 += begin_col; px2 += begin_col; for(int col=begin_col;col<end_col;col++, px1++, px2++) { px2->rgbtRed = (BYTE)blend(weight, px2->rgbtRed, px1->rgbtRed); px2->rgbtGreen = (BYTE)blend(weight, px2->rgbtGreen, px1->rgbtGreen); px2->rgbtBlue = (BYTE)blend(weight, px2->rgbtBlue, px1->rgbtBlue); } } surf1->Unlock(0); surf2->Unlock(0); return hr;}struct trible565 { uint16 v; trible565() : v(0) {} trible565(int _r, int _g, int _b) { lib::color_t rgb = (_b << 16) | (_g << 8) | _r ; v = (uint16)((rgb & 0xf80000)>> 8); v |= (uint16)(rgb & 0xfc00) >> 5; v |= (uint16)(rgb & 0xf8) >> 3; } trible565(uchar _r, uchar _g, uchar _b) { lib::color_t rgb = (_b << 16) | (_g << 8) | _r ; v = (uint16)((rgb & 0xf80000)>> 8); // red v |= (uint16)(rgb & 0xfc00) >> 5; // green v |= (uint16)(rgb & 0xf8) >> 3; // blue } trible565(lib::color_t rgb) { v = (uint16)((rgb & 0xf80000) >> 8); v |= (uint16)(rgb & 0xfc00) >> 5; v |= (uint16)(rgb & 0xf8) >> 3; } BYTE blue() { return (v & 0xf800) >> 8;} BYTE green() { return (v & 0x7e0) >> 2;} BYTE red() { return (v & 0x1f) << 3;}};HRESULT gui::dx::viewport::blt_blend16(const lib::rect& rc, double progress, IDirectDrawSurface *surf1, IDirectDrawSurface *surf2) { DDSURFACEDESC desc1, desc2; ZeroMemory(&desc1, sizeof(desc1)); desc1.dwSize = sizeof(desc1); ZeroMemory(&desc2, sizeof(desc2)); desc2.dwSize = sizeof(desc2); HRESULT hr = surf1->Lock(0, &desc1, DDLOCK_WAIT | DDLOCK_READONLY, 0); if(hr!=DD_OK) return hr; hr = surf2->Lock(0, &desc2, DDLOCK_WAIT, 0); if(hr != DD_OK) { surf1->Unlock(0); return hr; } lib::rect rcv(lib::point(0,0), lib::size(m_width,m_height)); lib::rect rcc = rc; rcc &= rcv; int begin_row = rcc.bottom(); int end_row = rcc.top(); int begin_col = rcc.left(); int end_col = rcc.right(); int weight = int(progress*256); for(int row = begin_row-1;row>=end_row;row--) { trible565* px1 = (trible565*)((BYTE*)desc1.lpSurface+row*desc1.lPitch); trible565* px2 = (trible565*)((BYTE*)desc2.lpSurface+row*desc2.lPitch); px1 += begin_col; px2 += begin_col; for(int col=begin_col;col<end_col;col++, px1++, px2++) { BYTE r = (BYTE)blend(weight, px2->red(), px1->red()); BYTE g = (BYTE)blend(weight, px2->green(), px1->green()); BYTE b = (BYTE)blend(weight, px2->blue(), px1->blue()); *px2 = trible565(r, g, b); } } surf1->Unlock(0); surf2->Unlock(0); return hr;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -