home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / gtk / screenarea.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-15  |  6.5 KB  |  294 lines

  1. // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
  2. // Copyright (C) 1999-2003 Forgotten
  3. // Copyright (C) 2004 Forgotten and the VBA development team
  4.  
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2, or(at your option)
  8. // any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software Foundation,
  17. // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  18.  
  19. #include "screenarea.h"
  20.  
  21. #include <string.h>
  22.  
  23. namespace VBA
  24. {
  25.  
  26. ScreenArea::ScreenArea(int _iWidth, int _iHeight, int _iScale) :
  27.   m_puiPixels(NULL),
  28.   m_puiDelta(NULL),
  29.   m_vFilter2x(NULL),
  30.   m_vFilterIB(NULL),
  31.   m_bShowCursor(true)
  32. {
  33.   g_assert(_iWidth >= 1 && _iHeight >= 1 && _iScale >= 1);
  34.  
  35.   m_iWidth  = _iWidth;
  36.   m_iHeight = _iHeight;
  37.   m_iScale  = _iScale;
  38.   vUpdateSize();
  39.  
  40.   set_events(Gdk::EXPOSURE_MASK
  41.              | Gdk::POINTER_MOTION_MASK
  42.              | Gdk::ENTER_NOTIFY_MASK
  43.              | Gdk::LEAVE_NOTIFY_MASK);
  44.  
  45.   char aiEmptyData[8];
  46.   memset(aiEmptyData, 0, sizeof(aiEmptyData));
  47.   Glib::RefPtr<Gdk::Bitmap> poSource = Gdk::Bitmap::create(aiEmptyData, 8, 8);
  48.   Glib::RefPtr<Gdk::Bitmap> poMask = Gdk::Bitmap::create(aiEmptyData, 8, 8);
  49.   Gdk::Color oFg;
  50.   Gdk::Color oBg;
  51.   oFg.set_rgb(0, 0, 0);
  52.   oBg.set_rgb(0, 0, 0);
  53.  
  54.   m_poEmptyCursor = new Gdk::Cursor(poSource, poMask, oFg, oBg, 0, 0);
  55. }
  56.  
  57. ScreenArea::~ScreenArea()
  58. {
  59.   if (m_puiPixels != NULL)
  60.   {
  61.     delete[] m_puiPixels;
  62.   }
  63.  
  64.   if (m_puiDelta != NULL)
  65.   {
  66.     delete[] m_puiDelta;
  67.   }
  68.  
  69.   if (m_poEmptyCursor != NULL)
  70.   {
  71.     delete m_poEmptyCursor;
  72.   }
  73. }
  74.  
  75. void ScreenArea::vSetSize(int _iWidth, int _iHeight)
  76. {
  77.   g_return_if_fail(_iWidth >= 1 && _iHeight >= 1);
  78.  
  79.   if (_iWidth != m_iWidth || _iHeight != m_iHeight)
  80.   {
  81.     m_iWidth  = _iWidth;
  82.     m_iHeight = _iHeight;
  83.     vUpdateSize();
  84.   }
  85. }
  86.  
  87. void ScreenArea::vSetScale(int _iScale)
  88. {
  89.   g_return_if_fail(_iScale >= 1);
  90.  
  91.   if (_iScale != m_iScale)
  92.   {
  93.     m_iScale = _iScale;
  94.     vUpdateSize();
  95.   }
  96. }
  97.  
  98. void ScreenArea::vSetFilter2x(EFilter2x _eFilter2x)
  99. {
  100.   m_vFilter2x = pvGetFilter2x(_eFilter2x, FilterDepth32);
  101. }
  102.  
  103. void ScreenArea::vSetFilterIB(EFilterIB _eFilterIB)
  104. {
  105.   m_vFilterIB = pvGetFilterIB(_eFilterIB, FilterDepth32);
  106. }
  107.  
  108. void ScreenArea::vDrawPixels(u8 * _puiData)
  109. {
  110.   if (m_vFilterIB != NULL)
  111.   {
  112.     m_vFilterIB(_puiData + m_iAreaWidth * 2 + 4,
  113.                 m_iAreaWidth * 2 + 4,
  114.                 m_iWidth,
  115.                 m_iHeight);
  116.   }
  117.  
  118.   if (m_iScale == 1)
  119.   {
  120.     u32 * puiSrc = (u32 *)_puiData + m_iWidth + 1;
  121.     u32 * puiPixel = m_puiPixels;
  122.     for (int y = 0; y < m_iHeight; y++)
  123.     {
  124.       for (int x = 0; x < m_iWidth; x++)
  125.       {
  126.         *puiPixel++ = *puiSrc++;
  127.       }
  128.       puiSrc++;
  129.     }
  130.   }
  131.   else if (m_iScale == 2 && m_vFilter2x != NULL)
  132.   {
  133.     m_vFilter2x(_puiData + m_iAreaWidth * 2 + 4,
  134.                 m_iAreaWidth * 2 + 4,
  135.                 m_puiDelta,
  136.                 (u8 *)m_puiPixels,
  137.                 m_iRowStride,
  138.                 m_iWidth,
  139.                 m_iHeight);
  140.   }
  141.   else
  142.   {
  143.     u32 * puiSrc = (u32 *)_puiData + m_iWidth + 1;
  144.     u32 * puiSrc2;
  145.     u32 * puiPixel = m_puiPixels;
  146.     for (int y = 0; y < m_iHeight; y++)
  147.     {
  148.       for (int j = 0; j < m_iScale; j++)
  149.       {
  150.         puiSrc2 = puiSrc;
  151.         for (int x = 0; x < m_iWidth; x++)
  152.         {
  153.           for (int i = 0; i < m_iScale; i++)
  154.           {
  155.             *puiPixel++ = *puiSrc2;
  156.           }
  157.           puiSrc2++;
  158.         }
  159.       }
  160.       puiSrc = puiSrc2 + 1;
  161.     }
  162.   }
  163.  
  164.   queue_draw_area(0, 0, m_iAreaWidth, m_iAreaHeight);
  165. }
  166.  
  167. void ScreenArea::vDrawColor(u32 _uiColor)
  168. {
  169.   _uiColor = GUINT32_TO_BE(_uiColor) << 8;
  170.  
  171.   u32 * puiPixel = m_puiPixels;
  172.   u32 * puiEnd   = m_puiPixels + m_iAreaWidth * m_iAreaHeight;
  173.   while (puiPixel != puiEnd)
  174.   {
  175.     *puiPixel++ = _uiColor;
  176.   }
  177.  
  178.   queue_draw_area(0, 0, m_iAreaWidth, m_iAreaHeight);
  179. }
  180.  
  181. void ScreenArea::vUpdateSize()
  182. {
  183.   if (m_puiPixels != NULL)
  184.   {
  185.     delete[] m_puiPixels;
  186.   }
  187.  
  188.   if (m_puiDelta != NULL)
  189.   {
  190.     delete[] m_puiDelta;
  191.   }
  192.  
  193.   m_iAreaWidth  = m_iScale * m_iWidth;
  194.   m_iAreaHeight = m_iScale * m_iHeight;
  195.   m_iRowStride  = m_iAreaWidth * 4;
  196.  
  197.   m_puiPixels = new u32[m_iAreaWidth * m_iAreaHeight];
  198.  
  199.   m_puiDelta = new u8[(m_iWidth + 2) * (m_iHeight + 2) * 4];
  200.   memset(m_puiDelta, 255, (m_iWidth + 2) * (m_iHeight + 2) * 4);
  201.  
  202.   set_size_request(m_iAreaWidth, m_iAreaHeight);
  203. }
  204.  
  205. void ScreenArea::vStartCursorTimeout()
  206. {
  207.   m_oCursorSig.disconnect();
  208.   m_oCursorSig = Glib::signal_timeout().connect(
  209.     SigC::slot(*this, &ScreenArea::bOnCursorTimeout),
  210.     2000);
  211. }
  212.  
  213. void ScreenArea::vStopCursorTimeout()
  214. {
  215.   m_oCursorSig.disconnect();
  216. }
  217.  
  218. void ScreenArea::vHideCursor()
  219. {
  220.   get_window()->set_cursor(*m_poEmptyCursor);
  221.   m_bShowCursor = false;
  222. }
  223.  
  224. void ScreenArea::vShowCursor()
  225. {
  226.   get_window()->set_cursor();
  227.   m_bShowCursor = true;
  228. }
  229.  
  230. bool ScreenArea::on_expose_event(GdkEventExpose * _pstEvent)
  231. {
  232.   if (_pstEvent->area.x + _pstEvent->area.width > m_iAreaWidth
  233.       || _pstEvent->area.y + _pstEvent->area.height > m_iAreaHeight)
  234.   {
  235.     return false;
  236.   }
  237.  
  238.   guchar * puiAreaPixels = (guchar *)m_puiPixels;
  239.  
  240.   if (_pstEvent->area.x != 0)
  241.   {
  242.     puiAreaPixels += _pstEvent->area.x << 2;
  243.   }
  244.  
  245.   if (_pstEvent->area.y != 0)
  246.   {
  247.     puiAreaPixels += _pstEvent->area.y * m_iRowStride;
  248.   }
  249.  
  250.   get_window()->draw_rgb_32_image(get_style()->get_fg_gc(get_state()),
  251.                                   _pstEvent->area.x,
  252.                                   _pstEvent->area.y,
  253.                                   _pstEvent->area.width,
  254.                                   _pstEvent->area.height,
  255.                                   Gdk::RGB_DITHER_MAX,
  256.                                   puiAreaPixels,
  257.                                   m_iRowStride);
  258.   return true;
  259. }
  260.  
  261. bool ScreenArea::on_motion_notify_event(GdkEventMotion * _pstEvent)
  262. {
  263.   if (! m_bShowCursor)
  264.   {
  265.     vShowCursor();
  266.   }
  267.   vStartCursorTimeout();
  268.   return false;
  269. }
  270.  
  271. bool ScreenArea::on_enter_notify_event(GdkEventCrossing * _pstEvent)
  272. {
  273.   vStartCursorTimeout();
  274.   return false;
  275. }
  276.  
  277. bool ScreenArea::on_leave_notify_event(GdkEventCrossing * _pstEvent)
  278. {
  279.   vStopCursorTimeout();
  280.   if (! m_bShowCursor)
  281.   {
  282.     vShowCursor();
  283.   }
  284.   return false;
  285. }
  286.  
  287. bool ScreenArea::bOnCursorTimeout()
  288. {
  289.   vHideCursor();
  290.   return false;
  291. }
  292.  
  293. } // namespace VBA
  294.