home *** CD-ROM | disk | FTP | other *** search
/ Chip 2004 July / CMCD0704.ISO / Software / Freeware / Utilitare / VisualBoyAdvance-1.7.2 / src / win32 / GBPrinterDlg.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2004-05-13  |  11.3 KB  |  495 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. // GBPrinter.cpp : implementation file
  20. //
  21.  
  22. #include "stdafx.h"
  23. #include "vba.h"
  24. #include "FileDlg.h"
  25. #include "GBPrinterDlg.h"
  26. #include "Reg.h"
  27. #include "WinResUtil.h"
  28.  
  29. #include "../System.h"
  30. #include "../NLS.h"
  31. #include "../Util.h"
  32.  
  33. extern "C" {
  34. #include <png.h>
  35. }
  36.  
  37. #ifdef _DEBUG
  38. #define new DEBUG_NEW
  39. #undef THIS_FILE
  40. static char THIS_FILE[] = __FILE__;
  41. #endif
  42.  
  43. /////////////////////////////////////////////////////////////////////////////
  44. // GBPrinter dialog
  45.  
  46.  
  47. GBPrinterDlg::GBPrinterDlg(CWnd* pParent /*=NULL*/)
  48.   : CDialog(GBPrinterDlg::IDD, pParent)
  49. {
  50.   //{{AFX_DATA_INIT(GBPrinterDlg)
  51.   m_scale = -1;
  52.   //}}AFX_DATA_INIT
  53.   bitmap = (BITMAPINFO *)bitmapHeader;
  54.   
  55.   bitmap->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  56.   bitmap->bmiHeader.biWidth = 160;
  57.   bitmap->bmiHeader.biHeight = -144;
  58.   bitmap->bmiHeader.biPlanes = 1;
  59.   bitmap->bmiHeader.biBitCount = 8;
  60.   bitmap->bmiHeader.biCompression = BI_RGB;
  61.   bitmap->bmiHeader.biSizeImage = 160*144;
  62.   bitmap->bmiHeader.biXPelsPerMeter = 0;
  63.   bitmap->bmiHeader.biYPelsPerMeter = 0;
  64.   bitmap->bmiHeader.biClrUsed = 4;
  65.   bitmap->bmiHeader.biClrImportant = 4;
  66.   bitmap->bmiColors[0].rgbBlue =
  67.     bitmap->bmiColors[0].rgbGreen =
  68.     bitmap->bmiColors[0].rgbRed =
  69.     255;
  70.   bitmap->bmiColors[0].rgbReserved = 0;
  71.   bitmap->bmiColors[1].rgbBlue =
  72.     bitmap->bmiColors[1].rgbGreen =
  73.     bitmap->bmiColors[1].rgbRed =
  74.     168;
  75.   bitmap->bmiColors[1].rgbReserved = 0;
  76.   bitmap->bmiColors[2].rgbBlue =
  77.     bitmap->bmiColors[2].rgbGreen =
  78.     bitmap->bmiColors[2].rgbRed =
  79.     96;
  80.   bitmap->bmiColors[2].rgbReserved = 0;
  81.   bitmap->bmiColors[3].rgbBlue =
  82.     bitmap->bmiColors[3].rgbGreen =
  83.     bitmap->bmiColors[3].rgbRed =
  84.     0;
  85.   bitmap->bmiColors[3].rgbReserved = 0;  
  86. }
  87.  
  88.  
  89. void GBPrinterDlg::DoDataExchange(CDataExchange* pDX)
  90. {
  91.   CDialog::DoDataExchange(pDX);
  92.   //{{AFX_DATA_MAP(GBPrinterDlg)
  93.   DDX_Radio(pDX, IDC_1X, m_scale);
  94.   //}}AFX_DATA_MAP
  95. }
  96.  
  97.  
  98. BEGIN_MESSAGE_MAP(GBPrinterDlg, CDialog)
  99.   //{{AFX_MSG_MAP(GBPrinterDlg)
  100.   ON_BN_CLICKED(ID_SAVE, OnSave)
  101.   ON_BN_CLICKED(ID_PRINT, OnPrint)
  102.   ON_BN_CLICKED(ID_OK, OnOk)
  103.   ON_BN_CLICKED(IDC_1X, On1x)
  104.   ON_BN_CLICKED(IDC_2X, On2x)
  105.   ON_BN_CLICKED(IDC_3X, On3x)
  106.   ON_BN_CLICKED(IDC_4X, On4x)
  107.   ON_WM_PAINT()
  108.   //}}AFX_MSG_MAP
  109.   END_MESSAGE_MAP()
  110.  
  111.   /////////////////////////////////////////////////////////////////////////////
  112. // GBPrinter message handlers
  113.  
  114. void GBPrinterDlg::saveAsBMP(const char *name)
  115. {
  116.   u8 writeBuffer[512 * 3];
  117.   
  118.   FILE *fp = fopen(name,"wb");
  119.  
  120.   if(!fp) {
  121.     systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s", name);
  122.     return;
  123.   }
  124.  
  125.   struct {
  126.     u8 ident[2];
  127.     u8 filesize[4];
  128.     u8 reserved[4];
  129.     u8 dataoffset[4];
  130.     u8 headersize[4];
  131.     u8 width[4];
  132.     u8 height[4];
  133.     u8 planes[2];
  134.     u8 bitsperpixel[2];
  135.     u8 compression[4];
  136.     u8 datasize[4];
  137.     u8 hres[4];
  138.     u8 vres[4];
  139.     u8 colors[4];
  140.     u8 importantcolors[4];
  141.     u8 pad[2];
  142.   } bmpheader;
  143.   memset(&bmpheader, 0, sizeof(bmpheader));
  144.  
  145.   bmpheader.ident[0] = 'B';
  146.   bmpheader.ident[1] = 'M';
  147.  
  148.   u32 fsz = sizeof(bmpheader) + 160*144*3;
  149.   utilPutDword(bmpheader.filesize, fsz);
  150.   utilPutDword(bmpheader.dataoffset, 0x38);
  151.   utilPutDword(bmpheader.headersize, 0x28);
  152.   utilPutDword(bmpheader.width, 160);
  153.   utilPutDword(bmpheader.height, 144);
  154.   utilPutDword(bmpheader.planes, 1);
  155.   utilPutDword(bmpheader.bitsperpixel, 24);
  156.   utilPutDword(bmpheader.datasize, 160*144);
  157.  
  158.   fwrite(&bmpheader, 1, sizeof(bmpheader), fp);
  159.  
  160.   u8 *b = writeBuffer;
  161.   u8 *data = (u8 *)bitmapData;
  162.   u8 *p = data + (160*143);
  163.   for(int y = 0; y < 144; y++) {
  164.     for(int x = 0; x < 160; x++) {
  165.       u8 c = *p++;
  166.       
  167.       *b++ = bitmap->bmiColors[c].rgbBlue;
  168.       *b++ = bitmap->bmiColors[c].rgbGreen;
  169.       *b++ = bitmap->bmiColors[c].rgbRed;
  170.     }
  171.     p -= 2*(160);
  172.     fwrite(writeBuffer, 1, 3*160, fp);
  173.     
  174.     b = writeBuffer;
  175.   }
  176.   
  177.   fclose(fp);
  178. }
  179.  
  180.  
  181. void GBPrinterDlg::saveAsPNG(const char *name)
  182. {
  183.   u8 writeBuffer[160 * 3];
  184.   
  185.   FILE *fp = fopen(name,"wb");
  186.  
  187.   if(!fp) {
  188.     systemMessage(MSG_ERROR_CREATING_FILE, "Error creating file %s",
  189.                   name);
  190.     return;
  191.   }
  192.   
  193.   png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
  194.                                                 NULL,
  195.                                                 NULL,
  196.                                                 NULL);
  197.   if(!png_ptr) {
  198.     fclose(fp);
  199.     return;
  200.   }
  201.  
  202.   png_infop info_ptr = png_create_info_struct(png_ptr);
  203.   
  204.   if(!info_ptr) {
  205.     png_destroy_write_struct(&png_ptr,NULL);
  206.     fclose(fp);
  207.     return;
  208.   }
  209.   
  210.   if(setjmp(png_ptr->jmpbuf)) {
  211.     png_destroy_write_struct(&png_ptr,NULL);
  212.     fclose(fp);
  213.     return;
  214.   }
  215.  
  216.   png_init_io(png_ptr,fp);
  217.  
  218.   png_set_IHDR(png_ptr,
  219.                info_ptr,
  220.                160,
  221.                144,
  222.                8,
  223.                PNG_COLOR_TYPE_RGB,
  224.                PNG_INTERLACE_NONE,
  225.                PNG_COMPRESSION_TYPE_DEFAULT,
  226.                PNG_FILTER_TYPE_DEFAULT);
  227.  
  228.   png_write_info(png_ptr,info_ptr);
  229.  
  230.   u8 *b = writeBuffer;
  231.  
  232.   int sizeX = 160;
  233.   int sizeY = 144;
  234.  
  235.   u8 *pixU8 = (u8 *)bitmapData;
  236.   for(int y = 0; y < sizeY; y++) {
  237.     for(int x = 0; x < sizeX; x++) {
  238.       u8 c = *pixU8++;
  239.       *b++ = bitmap->bmiColors[c].rgbRed;
  240.       *b++ = bitmap->bmiColors[c].rgbGreen;
  241.       *b++ = bitmap->bmiColors[c].rgbBlue;
  242.     }
  243.     png_write_row(png_ptr,writeBuffer);
  244.         
  245.     b = writeBuffer;
  246.   }
  247.   
  248.   png_write_end(png_ptr, info_ptr);
  249.  
  250.   png_destroy_write_struct(&png_ptr, &info_ptr);
  251.  
  252.   fclose(fp);  
  253. }
  254.  
  255.  
  256. void GBPrinterDlg::OnSave() 
  257. {
  258.   CString captureBuffer;
  259.  
  260.   if(theApp.captureFormat == 0)
  261.     captureBuffer = "printer.png";
  262.   else
  263.     captureBuffer = "printer.bmp";
  264.  
  265.   LPCTSTR exts[] = {".png", ".bmp" };
  266.  
  267.   CString filter = theApp.winLoadFilter(IDS_FILTER_PNG);
  268.   CString title = winResLoadString(IDS_SELECT_CAPTURE_NAME);
  269.  
  270.   FileDlg dlg(this,
  271.               captureBuffer,
  272.               filter,
  273.               theApp.captureFormat ? 2 : 1,
  274.               theApp.captureFormat ? "BMP" : "PNG",
  275.               exts,
  276.               "",
  277.               title,
  278.               true);
  279.  
  280.   if(dlg.DoModal() == IDCANCEL) {
  281.     return;
  282.   }
  283.  
  284.   captureBuffer = dlg.GetPathName();
  285.  
  286.   if(dlg.getFilterIndex() == 2)
  287.     saveAsBMP(captureBuffer);
  288.   else
  289.     saveAsPNG(captureBuffer);
  290. }
  291.  
  292. void GBPrinterDlg::OnPrint() 
  293. {
  294.   CPrintDialog dlg(FALSE);
  295.  
  296.   dlg.m_pd.nFromPage = 1;
  297.   dlg.m_pd.nToPage = 1;
  298.   dlg.m_pd.nMinPage = 1;
  299.   dlg.m_pd.nMaxPage = 1;
  300.   dlg.m_pd.nCopies = 1;
  301.  
  302.   if(dlg.DoModal() == IDOK) {
  303.     DOCINFO di;
  304.     float fLogPelsX1 = 0;
  305.     float fLogPelsX2 = 0;
  306.     float fLogPelsY1 = 0;
  307.     float fLogPelsY2 = 0;
  308.     float fScaleX = 0, fScaleY = 0;    
  309.     CDC *winDC = NULL;
  310.     memset(&di, 0, sizeof(di));
  311.     di.cbSize = sizeof(DOCINFO);
  312.     CString docName = winResLoadString(IDS_POCKET_PRINTER);
  313.     di.lpszDocName = docName;
  314.     CDC dc;
  315.     dc.Attach(dlg.GetPrinterDC());
  316.     int nError = dc.StartDoc(&di);
  317.  
  318.     if(nError == SP_ERROR) {
  319.       systemMessage(IDS_ERROR_ON_STARTDOC,"Error on StartDoc");
  320.       goto error;
  321.     }
  322.     nError = dc.StartPage();
  323.     if(nError <= 0) {
  324.       systemMessage(IDS_ERROR_ON_STARTPAGE, "Error on StartPage");
  325.       goto error;
  326.     }
  327.  
  328.     winDC = GetDC();
  329.     fLogPelsX1 = (float)winDC->GetDeviceCaps(LOGPIXELSX);
  330.     fLogPelsY1 = (float)winDC->GetDeviceCaps(LOGPIXELSY);
  331.     ReleaseDC(winDC);
  332.  
  333.     fLogPelsX2 = (float)dc.GetDeviceCaps(LOGPIXELSX);
  334.     fLogPelsY2 = (float)dc.GetDeviceCaps(LOGPIXELSY);
  335.     
  336.     if(fLogPelsX1 > fLogPelsX2)
  337.       fScaleX = fLogPelsX1 / fLogPelsX2;
  338.     else
  339.       fScaleX = fLogPelsX2 / fLogPelsX1;
  340.  
  341.     if(fLogPelsY1 > fLogPelsY2)
  342.       fScaleY = fLogPelsY1 / fLogPelsY2;
  343.     else
  344.       fScaleY = fLogPelsY2 / fLogPelsY1;
  345.  
  346.     fScaleX *= (scale+1);
  347.     fScaleY *= (scale+1);
  348.     
  349.     if(StretchDIBits(dc,
  350.                      0,
  351.                      0,
  352.                      (int)((float)160*fScaleX),
  353.                      (int)((float)144*fScaleY),
  354.                      0,
  355.                      0,
  356.                      160,
  357.                      144,
  358.                      bitmapData,
  359.                      bitmap,
  360.                      DIB_RGB_COLORS,
  361.                      SRCCOPY) == GDI_ERROR) {
  362.       systemMessage(IDS_ERROR_PRINTING_ON_STRETCH,
  363.                     "Error printing on StretchDIBits");
  364.     }
  365.  
  366.     nError = dc.EndPage();
  367.  
  368.     if(nError <= 0) {
  369.       systemMessage(IDS_ERROR_ON_ENDPAGE, "Error on EndPage");
  370.       goto error;
  371.     }
  372.  
  373.     nError = dc.EndDoc();
  374.  
  375.     if(nError <= 0)
  376.       systemMessage(IDS_ERROR_ON_ENDDOC, "Error on EndDoc");
  377.   error:
  378.     dc.DeleteDC();
  379.   }
  380. }
  381.  
  382. void GBPrinterDlg::processData(u8 *data)
  383. {
  384.   for(int y = 0; y < 0x12; y++) {
  385.     for(int x = 0; x < 0x14; x++) {
  386.       for(int k = 0; k < 8; k++) {
  387.         int a = *data++;
  388.         int b = *data++;
  389.         for(int j = 0; j < 8; j++) {
  390.           int mask = 1 << (7-j);
  391.           int c = 0;
  392.           if(a & mask)
  393.             c++;
  394.           if(b & mask)
  395.             c+=2;
  396.           bitmapData[x*8+j + 160*(y*8+k)] = c;
  397.         }
  398.       }
  399.     }
  400.   }  
  401. }
  402.  
  403.  
  404. BOOL GBPrinterDlg::OnInitDialog() 
  405. {
  406.   CDialog::OnInitDialog();
  407.   
  408.   scale = regQueryDwordValue("printerScale", 0);
  409.   if(scale < 0 || scale > 3)
  410.     scale = 0;
  411.   m_scale = scale;
  412.   UpdateData(FALSE);
  413.   
  414.   CenterWindow();
  415.   
  416.   return TRUE;  // return TRUE unless you set the focus to a control
  417.                 // EXCEPTION: OCX Property Pages should return FALSE
  418. }
  419.  
  420. void GBPrinterDlg::OnOk() 
  421. {
  422.   EndDialog(TRUE);
  423. }
  424.  
  425. void GBPrinterDlg::On1x() 
  426. {
  427.   regSetDwordValue("printerScale", 0);
  428.   scale = 0;
  429. }
  430.  
  431. void GBPrinterDlg::On2x() 
  432. {
  433.   regSetDwordValue("printerScale", 1);
  434.   scale = 1;
  435. }
  436.  
  437. void GBPrinterDlg::On3x() 
  438. {
  439.   regSetDwordValue("printerScale", 2);
  440.   scale = 2;
  441. }
  442.  
  443. void GBPrinterDlg::On4x() 
  444. {
  445.   regSetDwordValue("printerScale", 3);
  446.   scale = 3;
  447. }
  448.  
  449. void GBPrinterDlg::OnPaint() 
  450. {
  451.   CPaintDC dc(this); // device context for painting
  452.   
  453.   RECT rect;
  454.   CWnd *h = GetDlgItem(IDC_GB_PRINTER);
  455.   h->GetWindowRect(&rect);
  456.   POINT p;
  457.   p.x = rect.left;
  458.   p.y = rect.top;
  459.   ScreenToClient((POINT *)&p);
  460.   rect.left = p.x+1;
  461.   rect.top = p.y+1;
  462.   p.x = rect.right;
  463.   p.y = rect.bottom;
  464.   ScreenToClient((POINT *)&p);
  465.   rect.right = p.x-1;
  466.   rect.bottom = p.y-1;
  467.   
  468.   StretchDIBits(dc,
  469.                 rect.left,
  470.                 rect.top,
  471.                 rect.right - rect.left,
  472.                 rect.bottom - rect.top,
  473.                 0,
  474.                 0,
  475.                 160,
  476.                 144,
  477.                 bitmapData,
  478.                 bitmap,
  479.                 DIB_RGB_COLORS,
  480.                 SRCCOPY);
  481. }
  482.  
  483. void systemGbPrint(u8 *data,
  484.                    int pages,
  485.                    int feed,
  486.                    int palette,
  487.                    int contrast)
  488. {
  489.   theApp.winCheckFullscreen();
  490.   GBPrinterDlg printer;
  491.   printer.processData(data);
  492.   printer.DoModal();
  493. }
  494.  
  495.