]> git.saurik.com Git - wxWidgets.git/blobdiff - src/x11/bitmap.cpp
unapplied part of Dimitri's patch at his request
[wxWidgets.git] / src / x11 / bitmap.cpp
index 646ad0cb1aac58d8cdc6085e9bfd06b06beab18f..214d4554f7c20f5a31786a995ec1b8e07564ec12 100644 (file)
@@ -28,6 +28,9 @@
 #if wxUSE_NANOX
 #undef wxHAVE_LIB_XPM
 #define wxHAVE_LIB_XPM 0
 #if wxUSE_NANOX
 #undef wxHAVE_LIB_XPM
 #define wxHAVE_LIB_XPM 0
+
+// Copy from the drawable to the wxImage
+bool wxGetImageFromDrawable(GR_DRAW_ID drawable, int srcX, int srcY, int width, int height, wxImage& image);
 #endif
 
 #if wxUSE_XPM
 #endif
 
 #if wxUSE_XPM
@@ -312,10 +315,10 @@ bool wxBitmap::Create( int width, int height, int depth )
     M_BMPDATA->m_height = height;
 
 #if wxUSE_NANOX
     M_BMPDATA->m_height = height;
 
 #if wxUSE_NANOX
-    M_BMPDATA->m_bitmap = (WXPixmap) GrNewPixmap(width, height, NULL);
+    M_BMPDATA->m_pixmap = (WXPixmap) GrNewPixmap(width, height, NULL);
     M_BMPDATA->m_bpp = bpp;
 
     M_BMPDATA->m_bpp = bpp;
 
-    wxASSERT_MSG( M_BMPDATA->m_bitmap, wxT("Bitmap creation failed") );
+    wxASSERT_MSG( M_BMPDATA->m_pixmap, wxT("Bitmap creation failed") );
 #else
     if (depth == 1)
     {
 #else
     if (depth == 1)
     {
@@ -426,13 +429,49 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
     if (!Create(w, h, depth))
         return FALSE;
 
     if (!Create(w, h, depth))
         return FALSE;
 
-    wxMemoryDC memDC;
-    memDC.SelectObject(*this);
+    // Unfortunately the mask has to be screen-depth since
+    // 1-bpp bitmaps don't seem to be supported
+    // TODO: implement transparent drawing, presumably
+    // by doing several blits as per the Windows
+    // implementation because Nano-X doesn't support
+    // XSetClipMask.
+    // TODO: could perhaps speed this function up
+    // by making a buffer of pixel values,
+    // and then calling GrArea to write that to the
+    // pixmap. See demos/nxroach.c.
+
+    bool hasMask = image.HasMask();
+    
+    GC pixmapGC = GrNewGC();
+    Pixmap pixmap = (Pixmap) GetPixmap();
+
+    GC maskGC = 0;
+    Pixmap maskPixmap = 0;
 
 
-    // Warning: this is very inefficient.
-    wxPen pen;
-    pen.SetStyle(wxSOLID);
-    pen.SetWidth(1);
+    unsigned char maskR = 0;
+    unsigned char maskG = 0;
+    unsigned char maskB = 0;
+
+    if (hasMask)
+    {
+        maskR = image.GetMaskRed();
+        maskG = image.GetMaskGreen();
+        maskB = image.GetMaskBlue();
+        
+        maskGC = GrNewGC();
+        maskPixmap = GrNewPixmap(w, h, 0);
+        if (!maskPixmap)
+            hasMask = FALSE;
+        else
+        {
+            wxMask* mask = new wxMask;
+            mask->SetBitmap((WXPixmap) maskPixmap);
+            SetMask(mask);
+        }
+    }
+
+    GR_COLOR lastPixmapColour = 0;
+    GR_COLOR lastMaskColour = 0;
     
     int i, j;
     for (i = 0; i < w; i++)
     
     int i, j;
     for (i = 0; i < w; i++)
@@ -442,26 +481,43 @@ bool wxBitmap::CreateFromImage( const wxImage& image, int depth )
             unsigned char red = image.GetRed(i, j);
             unsigned char green = image.GetGreen(i, j);
             unsigned char blue = image.GetBlue(i, j);
             unsigned char red = image.GetRed(i, j);
             unsigned char green = image.GetGreen(i, j);
             unsigned char blue = image.GetBlue(i, j);
-            wxColour colour(red, green, blue);
 
 
-            pen.SetColour(colour);
-            memDC.SetPen(pen);
-            memDC.DrawPoint(i, j);
+            GR_COLOR colour = GR_RGB(red, green, blue);
+
+            // Efficiency measure
+            if (colour != lastPixmapColour || (i == 0 && j == 0))
+            {
+                GrSetGCForeground(pixmapGC, colour);
+                lastPixmapColour = colour;
+            }
+            
+            GrPoint(pixmap, pixmapGC, i, j);
             
             
-#if 0
             if (hasMask)
             {
                 // scan the bitmap for the transparent colour and set the corresponding
                 // pixels in the mask to BLACK and the rest to WHITE
                 if (maskR == red && maskG == green && maskB == blue)
             if (hasMask)
             {
                 // scan the bitmap for the transparent colour and set the corresponding
                 // pixels in the mask to BLACK and the rest to WHITE
                 if (maskR == red && maskG == green && maskB == blue)
-                    ::SetPixel(hMaskDC, i, j, PALETTERGB(0, 0, 0));
+                {
+                    colour = GR_RGB(0, 0, 0);
+                }
                 else
                 else
-                    ::SetPixel(hMaskDC, i, j, PALETTERGB(255, 255, 255));
+                {
+                    colour = GR_RGB(255, 255, 255);
+                }
+                if (colour != lastMaskColour || (i == 0 && j == 0))
+                {
+                    GrSetGCForeground(maskGC, colour);
+                    lastMaskColour = colour;
+                }
+                GrPoint(maskPixmap, maskGC, i, j);
             }
             }
-#endif
         }
     }
         }
     }
-    memDC.SelectObject(wxNullBitmap);
+
+    GrDestroyGC(pixmapGC);
+    if (hasMask)
+        GrDestroyGC(maskGC);
     
     return TRUE;
 #else
     
     return TRUE;
 #else
@@ -751,33 +807,8 @@ wxImage wxBitmap::ConvertToImage() const
     int bpp = DefaultDepth( xdisplay, xscreen );
 
 #if wxUSE_NANOX
     int bpp = DefaultDepth( xdisplay, xscreen );
 
 #if wxUSE_NANOX
-    int w = image.GetWidth();
-    int h = image.GetHeight();
-    
-    wxMemoryDC memDC;
-    memDC.SelectObject(*this);
-
-    wxColour pixelCol;
-
-    // Warning: this is very inefficient.
-    int i, j;
-    for (i = 0; i < w; i++)
-    {
-        for (j = 0; j < h; j++)
-        {
-            memDC.GetPixel(i, j, & pixelCol);
-
-            // TODO: make wxColour accessors more efficient
-            // by inlining, if possible
-            image.SetRGB(i, j,
-                         pixelCol.Red(), pixelCol.Green(),
-                         pixelCol.Blue());
-        }
-    }
-    memDC.SelectObject(wxNullBitmap);
-
+    wxGetImageFromDrawable((Pixmap) GetPixmap(), 0, 0, GetWidth(), GetHeight(), image);
     return image;
     return image;
-    
 #else
     // !wxUSE_NANOX
     XImage *x_image = NULL;
 #else
     // !wxUSE_NANOX
     XImage *x_image = NULL;
@@ -1246,3 +1277,140 @@ WXDisplay *wxBitmap::GetDisplay() const
     return M_BMPDATA->m_display;
 }
 
     return M_BMPDATA->m_display;
 }
 
+#if wxUSE_NANOX
+// Copy from the drawable to the wxImage
+bool wxGetImageFromDrawable(GR_DRAW_ID drawable, int srcX, int srcY, int width, int height, wxImage& image)
+{
+    GR_SCREEN_INFO sinfo;
+    int x, y;
+    GR_PIXELVAL *pixels;
+    GR_PALETTE* palette = NULL;
+    unsigned char rgb[3], *pp;
+
+    GrGetScreenInfo(&sinfo);
+
+    if (sinfo.pixtype == MWPF_PALETTE) {
+               if(!(palette = (GR_PALETTE*) malloc(sizeof(GR_PALETTE)))) {
+                       return FALSE;
+               }
+               GrGetSystemPalette(palette);
+       }
+
+    if(!(pixels = (GR_PIXELVAL*) malloc(sizeof(GR_PIXELVAL) * width * height)))
+    {
+        return FALSE;
+    }
+
+    image.Create(width, height);
+
+       GrReadArea(drawable, srcX, srcY, width, height,
+                                               pixels);
+
+
+               for(x = 0; x < sinfo.cols; x++) {
+
+                       pp = (unsigned char *)pixels +
+                               ((x + (y * sinfo.cols)) *
+                               sizeof(GR_PIXELVAL));
+
+                       switch(sinfo.pixtype) {
+                       /* FIXME: These may need modifying on big endian. */
+                               case MWPF_TRUECOLOR0888:
+                               case MWPF_TRUECOLOR888:
+                                       rgb[0] = pp[2];
+                                       rgb[1] = pp[1];
+                                       rgb[2] = pp[0];
+                                       break;
+                               case MWPF_PALETTE:
+                                       rgb[0] = palette->palette[pp[0]].r;
+                                       rgb[1] = palette->palette[pp[0]].g;
+                                       rgb[2] = palette->palette[pp[0]].b;
+                                       break;
+                               case MWPF_TRUECOLOR565:
+                                       rgb[0] = pp[1] & 0xf8;
+                                       rgb[1] = ((pp[1] & 0x07) << 5) |
+                                               ((pp[0] & 0xe0) >> 3);
+                                       rgb[2] = (pp[0] & 0x1f) << 3;
+                                       break;
+                               case MWPF_TRUECOLOR555:
+                                       rgb[0] = (pp[1] & 0x7c) << 1;
+                                       rgb[1] = ((pp[1] & 0x03) << 6) |
+                                               ((pp[0] & 0xe0) >> 2);
+                                       rgb[2] = (pp[0] & 0x1f) << 3;
+                                       break;
+                               case MWPF_TRUECOLOR332:
+                                       rgb[0] = pp[0] & 0xe0;
+                                       rgb[1] = (pp[0] & 0x1c) << 3;
+                                       rgb[2] = (pp[0] & 0x03) << 6;
+                                       break;
+                               default:
+                                       fprintf(stderr, "Unsupported pixel "
+                                                       "format\n");
+                                       return 1;
+                       }
+
+            image.SetRGB(x, y, rgb[0], rgb[1], rgb[2]);
+
+       }
+
+    free(pixels);
+    if(palette) free(palette);
+
+    return TRUE;
+}
+
+#if 0
+int GrGetPixelColor(GR_SCREEN_INFO* sinfo, GR_PALETTE* palette, GR_PIXELVAL pixel,
+    unsigned char* red, unsigned char* green, unsigned char* blue)
+{
+       unsigned char rgb[3], *pp;
+
+    pp = (unsigned char*) & pixel ;
+
+    switch (sinfo.pixtype)
+    {
+                       /* FIXME: These may need modifying on big endian. */
+                               case MWPF_TRUECOLOR0888:
+                               case MWPF_TRUECOLOR888:
+                                       rgb[0] = pp[2];
+                                       rgb[1] = pp[1];
+                                       rgb[2] = pp[0];
+                                       break;
+                               case MWPF_PALETTE:
+                                       rgb[0] = palette->palette[pp[0]].r;
+                                       rgb[1] = palette->palette[pp[0]].g;
+                                       rgb[2] = palette->palette[pp[0]].b;
+                                       break;
+                               case MWPF_TRUECOLOR565:
+                                       rgb[0] = pp[1] & 0xf8;
+                                       rgb[1] = ((pp[1] & 0x07) << 5) |
+                                               ((pp[0] & 0xe0) >> 3);
+                                       rgb[2] = (pp[0] & 0x1f) << 3;
+                                       break;
+                               case MWPF_TRUECOLOR555:
+                                       rgb[0] = (pp[1] & 0x7c) << 1;
+                                       rgb[1] = ((pp[1] & 0x03) << 6) |
+                                               ((pp[0] & 0xe0) >> 2);
+                                       rgb[2] = (pp[0] & 0x1f) << 3;
+                                       break;
+                               case MWPF_TRUECOLOR332:
+                                       rgb[0] = pp[0] & 0xe0;
+                                       rgb[1] = (pp[0] & 0x1c) << 3;
+                                       rgb[2] = (pp[0] & 0x03) << 6;
+                                       break;
+                               default:
+                                       fprintf(stderr, "Unsupported pixel format\n");
+                                       return 0;
+       }
+
+
+    *(red) = rgb[0];
+    *(green) = rgb[1];
+    *(blue) = rgb[2];
+    return 1;
+}
+#endif
+
+#endif
+  // wxUSE_NANOX
+