home *** CD-ROM | disk | FTP | other *** search
/ PC Format (South-Africa) 2001 June / PCFJune.iso / Xenon / XenonSource.exe / gamesystem / source / gs_image.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-08  |  9.8 KB  |  476 lines

  1. //-------------------------------------------------------------
  2. //
  3. // Class:    gsCImage
  4. //
  5. // Author:    John M Phillips
  6. //
  7. // Started:    12/03/00
  8. //
  9. // Base:    gsCVisual
  10. //
  11. // Derived:    None
  12. //
  13. //-------------------------------------------------------------
  14.  
  15. #include "gamesystem.h"
  16.  
  17. //-------------------------------------------------------------
  18.  
  19. gsCImage::gsCImage()
  20. {
  21.     m_rect = gsCRect(gsCPoint(0,0),gsCPoint(0,0));
  22.     m_surface = 0;
  23.     m_colour_key = 0;
  24.     m_isLocked = false;
  25. }
  26.  
  27. //-------------------------------------------------------------
  28.  
  29. gsCImage::~gsCImage()
  30. {
  31.     destroy();
  32. }
  33.  
  34. //-------------------------------------------------------------
  35.  
  36. bool gsCImage::load(const char *filename,bool rescale)
  37. {
  38.     char fullname[_MAX_PATH];
  39.  
  40.     if (!gsCFile::getFullName(filename,fullname)) {
  41.         gsREPORT("gsCImage::load couldn't find file");
  42.         return false;
  43.         }
  44.     
  45.     HBITMAP hbm = (HBITMAP) LoadImage(NULL,
  46.                                       fullname,
  47.                                       IMAGE_BITMAP,
  48.                                       0,0,
  49.                                       LR_LOADFROMFILE | LR_CREATEDIBSECTION);
  50.  
  51.     if (hbm == NULL) {
  52.         gsREPORT("gsCImage::load couldn't load bitmap");
  53.         return false;
  54.         }
  55.  
  56.     HDC hdcImage = CreateCompatibleDC(NULL);
  57.  
  58.     if (!hdcImage) {
  59.         gsREPORT("gsCImage::load couldn't create compatible device context");
  60.         return false;
  61.         }
  62.     
  63.     SelectObject(hdcImage,hbm);
  64.     
  65.     BITMAP bm;
  66.     GetObject(hbm,sizeof(bm),&bm);
  67.  
  68.     if (m_surface == NULL) {
  69.         if (!setSize(gsCPoint(bm.bmWidth,bm.bmHeight))) {
  70.             gsREPORT("gsCImage::load couldn't create surface of required size");
  71.             return false;
  72.             }
  73.         }
  74.     else {
  75.         m_surface->Restore();
  76.         if (!rescale) {
  77.             if (!setSize(gsCPoint(bm.bmWidth,bm.bmHeight))) {
  78.                 gsREPORT("gsCImage::load couldn't create surface of required size");
  79.                 return false;
  80.                 }
  81.             }
  82.         }
  83.  
  84.     gsDDSURFACEDESC ddsd;
  85.     ddsd.dwSize = sizeof(ddsd);
  86.     ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH;
  87.     m_surface->GetSurfaceDesc(&ddsd);
  88.  
  89.     HDC hdc;
  90.  
  91.     // NOTE: don't single step through the next 3 lines
  92.     // remote debugger doesn't like surface lock
  93.  
  94.     HRESULT hr;
  95.  
  96.     hr = m_surface->GetDC(&hdc);
  97.  
  98.     if (hr != DD_OK) {
  99.         gsREPORT("gsCImage::load couldn't get device context");
  100.         return false;
  101.         }
  102.  
  103.     StretchBlt(hdc,0,0,ddsd.dwWidth,ddsd.dwHeight,hdcImage,0,0,bm.bmWidth,bm.bmHeight,SRCCOPY);
  104.     m_surface->ReleaseDC(hdc);
  105.     
  106.     DeleteDC(hdcImage);
  107.  
  108.     DeleteObject(hbm);
  109.  
  110.     return true;
  111. }
  112.  
  113. //-------------------------------------------------------------
  114.  
  115. bool gsCImage::setSize(const gsCPoint& size)
  116. {
  117.     destroy();
  118.     return create(size);
  119. }
  120.  
  121. //-------------------------------------------------------------
  122.  
  123. bool gsCImage::enableColourKey(const gsCColour& colour)
  124. {
  125.     if (m_surface) {
  126.         DDCOLORKEY ddck;
  127.         ddck.dwColorSpaceLowValue = ddck.dwColorSpaceHighValue = colour.getRaw();
  128.         m_surface->SetColorKey(DDCKEY_SRCBLT,&ddck);
  129.         m_colour_key = DDBLT_KEYSRC;
  130.         }
  131.  
  132.     return true;
  133. }
  134.  
  135. //-------------------------------------------------------------
  136.  
  137. bool gsCImage::disableColourKey()
  138. {
  139.     if (m_surface) {
  140.         m_surface->SetColorKey(DDCKEY_SRCBLT,NULL);
  141.         m_colour_key = 0;
  142.         }
  143.  
  144.     return true;
  145. }
  146.  
  147. //-------------------------------------------------------------
  148.  
  149. void gsCImage::fill(const gsCColour& colour)
  150. {
  151.     if (m_surface) {
  152.         DDBLTFX ddbltfx;
  153.         ddbltfx.dwSize = sizeof(DDBLTFX);
  154.         ddbltfx.dwFillColor = colour.getRaw();
  155.  
  156.         HRESULT hr;
  157.  
  158.         hr = m_surface->Blt(NULL,
  159.                             NULL,
  160.                             NULL,
  161.                             DDBLT_COLORFILL | DDBLT_WAIT,
  162.                             &ddbltfx);
  163.  
  164.         if (hr != DD_OK)
  165.             gsREPORT("gsCImage::fill blit failed");
  166.         }
  167. }
  168.  
  169. //-------------------------------------------------------------
  170.  
  171. bool gsCImage::setPoint(const gsCPoint& point,const gsCColour& colour)
  172. {
  173.     if (!m_surface) {
  174.         gsREPORT("gsCImage::setPixel called with no surface");
  175.         return false;
  176.         }
  177.  
  178.     if (m_rect.contains(point)) {
  179.  
  180.         DDBLTFX ddbltfx;
  181.         ddbltfx.dwSize = sizeof(DDBLTFX);
  182.         ddbltfx.dwFillColor = colour.getRaw();
  183.  
  184.         gsCRect dest(point,point + gsCPoint(1,1));
  185.  
  186.         HRESULT hr;
  187.  
  188.         hr = m_surface->Blt(LPRECT(dest),
  189.                             NULL,
  190.                             NULL,
  191.                             DDBLT_COLORFILL | DDBLT_WAIT,
  192.                             &ddbltfx);
  193.  
  194.         if (hr != DD_OK) {
  195.             gsREPORT("gsCImage::setPoint blit failed");
  196.             return false;
  197.             }
  198.  
  199.         return true;
  200.         }
  201.  
  202.     return false;
  203. }
  204.  
  205. //-------------------------------------------------------------
  206.  
  207. bool gsCImage::setRect(const gsCRect& rect,const gsCColour& colour)
  208. {
  209.     if (!m_surface) {
  210.         gsREPORT("gsCImage::setBox called with no surface");
  211.         return false;
  212.         }
  213.  
  214.     for (int x = 0; x <= rect.getWidth(); x++) {
  215.         setPoint(gsCPoint(x,rect.getTop()),colour);
  216.         setPoint(gsCPoint(x,rect.getBottom()),colour);
  217.         }
  218.     for (int y = 0; y <= rect.getHeight(); y++) {
  219.         setPoint(gsCPoint(rect.getLeft(),y),colour);
  220.         setPoint(gsCPoint(rect.getRight(),y),colour);
  221.         }
  222.  
  223.     return true;
  224. }
  225.  
  226. //-------------------------------------------------------------
  227.  
  228. bool gsCImage::create(const gsCPoint& size)
  229. {
  230.     if (m_direct_draw) {
  231.         m_rect = gsCRect(gsCPoint(0,0),size);
  232.     
  233.         gsDDSURFACEDESC ddsd;
  234.  
  235.         ZeroMemory(&ddsd,sizeof(ddsd));
  236.         ddsd.dwSize = sizeof(ddsd);
  237.         ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
  238.         ddsd.dwWidth = m_rect.getWidth();
  239.         ddsd.dwHeight = m_rect.getHeight();
  240.         ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
  241.  
  242.         HRESULT hr;
  243.  
  244.         hr = m_direct_draw->CreateSurface(&ddsd,&m_surface,NULL);
  245.  
  246.         if (hr != DD_OK) {
  247.             gsREPORT("gsCImage::create couldn't create surface");
  248.             return false;
  249.             }
  250.  
  251. //        gsREPORT("gsCImage created");
  252.  
  253.         return true;
  254.         }
  255.     else {
  256.         gsREPORT("gsCImage::create called with no direct draw device");
  257.         return false;
  258.         }
  259. }
  260.  
  261. //-------------------------------------------------------------
  262.  
  263. void gsCImage::destroy()
  264. {
  265.     if (m_surface) {
  266.         m_surface->Release();
  267.         m_surface = 0;
  268.  
  269. //        gsREPORT("gsCImage destroyed");
  270.         }
  271. }
  272.  
  273. //-------------------------------------------------------------
  274.  
  275. bool gsCImage::draw(const gsCPoint& position)
  276. {
  277.     if (!m_direct_draw) {
  278.         gsREPORT("gsCImage::draw called with no direct draw device");
  279.         return false;
  280.         }
  281.  
  282.     gsCScreen *screen = gsCApplication::getScreen();
  283.  
  284.     if (!screen) {
  285.         gsREPORT("gsCImage::draw called with no active screen");
  286.         return false;
  287.         }
  288.  
  289.     gsCRect dest(position,position + m_rect.getSize());
  290.  
  291.     if (screen->getRect().contains(dest)) {
  292.  
  293.         HRESULT hr;
  294.  
  295.         hr = screen->getBackSurface()->Blt(LPRECT(dest),
  296.                                            m_surface,
  297.                                            NULL,
  298.                                            DDBLT_WAIT | m_colour_key,
  299.                                            NULL);
  300.  
  301.         if (hr != DD_OK) {
  302.             gsREPORT("gsCImage::draw blit failed");
  303.             return false;
  304.             }
  305.  
  306.         }
  307.     else {
  308.         if (!screen->getRect().overlaps(dest))
  309.             return false;
  310.  
  311.         gsCRect source = m_rect;
  312.  
  313.         screen->getRect().clip(source,dest);
  314.  
  315.         HRESULT hr;
  316.  
  317.         hr = screen->getBackSurface()->Blt(LPRECT(dest),
  318.                                            m_surface,
  319.                                            LPRECT(source),
  320.                                            DDBLT_WAIT | m_colour_key,
  321.                                            NULL);
  322.  
  323.         if (hr != DD_OK) {
  324.             gsREPORT("gsCImage::draw blit failed");
  325.             return false;
  326.             }
  327.         }
  328.  
  329.     return true;
  330. }
  331.  
  332. //-------------------------------------------------------------
  333. // Draw sprite in solid colour
  334.  
  335. bool gsCImage::drawSolid(const gsCPoint& position,const gsCColour& fill_colour)
  336. {
  337.     if (!m_direct_draw) {
  338.         gsREPORT("gsCImage::draw called with no direct draw device");
  339.         return false;
  340.         }
  341.  
  342.     gsCScreen *screen = gsCApplication::getScreen();
  343.  
  344.     if (!screen) {
  345.         gsREPORT("gsCImage::draw called with no active screen");
  346.         return false;
  347.         }
  348.  
  349.     gsCRect dest(position,position + m_rect.getSize());
  350.  
  351.     if (screen->getRect().contains(dest)) {
  352.  
  353.         bool ok = false;
  354.  
  355.         if (lock()) {
  356.             ok = screen->bltSolid(dest,m_ddsd,m_rect,fill_colour);
  357.             unlock();
  358.             }
  359.         
  360.         if (!ok) {
  361.             gsREPORT("gsCImage::drawSolid blit failed");
  362.             return false;
  363.             }
  364.         }
  365.     else {
  366.         if (!screen->getRect().overlaps(dest))
  367.             return false;
  368.  
  369.         gsCRect source = m_rect;
  370.  
  371.         screen->getRect().clip(source,dest);
  372.  
  373.         bool ok = false;
  374.  
  375.         if (lock()) {
  376.             ok = screen->bltSolid(dest,m_ddsd,source,fill_colour);
  377.             unlock();
  378.             }
  379.         if (!ok) {
  380.             gsREPORT("gsCImage::drawSolid blit failed");
  381.             return false;
  382.             }
  383.         }
  384.  
  385.     return true;
  386. }
  387.  
  388. //-------------------------------------------------------------
  389.  
  390. bool gsCImage::drawFast(const gsCPoint& position)
  391. {
  392.     gsCScreen *screen = gsCApplication::getScreen();
  393.  
  394.     HRESULT hr;
  395.  
  396.     gsCRect dest(position,position + m_rect.getSize());
  397.  
  398.     hr = screen->getBackSurface()->Blt(LPRECT(dest),
  399.                                        m_surface,
  400.                                        NULL,
  401.                                        DDBLT_WAIT | m_colour_key,
  402.                                        NULL);
  403.  
  404.     if (hr != DD_OK) {
  405.         gsREPORT("gsCImage::drawFast blit failed");
  406.         return false;
  407.         }
  408.  
  409.     return true;
  410. }
  411.  
  412. //-------------------------------------------------------------
  413.  
  414. bool gsCImage::lock()
  415. {
  416.     if (!m_isLocked) {
  417.     
  418.         HRESULT hr;
  419.         
  420.         memset(&m_ddsd,0,sizeof(m_ddsd));
  421.         m_ddsd.dwSize = sizeof(m_ddsd);
  422.  
  423. #ifdef gsALLOW_SYSLOCK
  424.         hr = m_surface->Lock(NULL,&m_ddsd,DDLOCK_WAIT | DDLOCK_NOSYSLOCK,NULL);
  425. #else
  426.         hr = m_surface->Lock(NULL,&m_ddsd,DDLOCK_WAIT,NULL);
  427. #endif
  428.         
  429.         while (hr == DDERR_SURFACELOST) {
  430.             m_surface->Restore();
  431.  
  432.             memset(&m_ddsd,0,sizeof(m_ddsd));
  433.             m_ddsd.dwSize = sizeof(m_ddsd);
  434.         
  435. #ifdef gsALLOW_SYSLOCK
  436.             hr = m_surface->Lock(NULL,&m_ddsd,DDLOCK_WAIT | DDLOCK_NOSYSLOCK,NULL);
  437. #else
  438.             hr = m_surface->Lock(NULL,&m_ddsd,DDLOCK_WAIT,NULL);
  439. #endif
  440.             }
  441.         
  442.         if (hr != DD_OK) {
  443.             gsERROR("gsCImage::lock failed");
  444.             return false;
  445.             }
  446.  
  447.         m_isLocked = true;
  448.         }
  449.  
  450.     return true;
  451. }
  452.  
  453. //-------------------------------------------------------------
  454.  
  455. void gsCImage::unlock()
  456. {
  457.     if (m_isLocked) {
  458.         HRESULT hr;
  459.     
  460.         hr = m_surface->Unlock(NULL);
  461.  
  462.         while (hr == DDERR_SURFACELOST) {
  463.             m_surface->Restore();
  464.             hr = m_surface->Unlock(NULL);
  465.             }
  466.  
  467.         if (hr != DD_OK)
  468.             gsERROR("gsCImage::unlock failed");
  469.  
  470.         m_isLocked = false;
  471.         }
  472. }
  473.  
  474. //-------------------------------------------------------------
  475.  
  476.