KSM edits to RA8875

Dependents:   Liz_Test_Code

Revision:
96:40b74dd3695b
Parent:
95:ef538bd687c0
Child:
97:03c509c3db18
Child:
98:ecebed9b80b2
--- a/RA8875.cpp	Tue Jul 07 17:05:59 2015 +0000
+++ b/RA8875.cpp	Sat Nov 28 15:39:44 2015 +0000
@@ -97,6 +97,9 @@
     , cs(csel)
     , res(reset)
 {
+    c_callback = NULL;
+    obj_callback = NULL;
+    method_callback = NULL;
 }
 
 //RA8875::~RA8875()
@@ -1587,9 +1590,205 @@
 RetCode_t RA8875::PrintScreen(uint16_t layer, loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP)
 {
     (void)layer;
+    
+    // AttachPrintHandler(this, RA8875::_printCallback);
+    // return PrintScreen(x,y,w,h);
     return PrintScreen(x, y, w, h, Name_BMP);
 }
 
+RetCode_t RA8875::_printCallback(RA8875::filecmd_t cmd, uint8_t * buffer, uint16_t size)
+{
+    HexDump("CB", buffer, size);
+    switch(cmd) {
+        case RA8875::OPEN:
+            //pc.printf("About to write %lu bytes\r\n", *(uint32_t *)buffer);
+            _printFH = fopen("file.bmp", "w+b");
+            if (_printFH == 0)
+                return file_not_found;
+            break;
+        case RA8875::WRITE:
+            //pc.printf("  Write %4u bytes\r\n", size);
+            fwrite(buffer, 1, size, _printFH);
+            break;
+        case RA8875::CLOSE:
+            //pc.printf("  close\r\n");
+            fclose(_printFH);
+            _printFH = 0;
+            break;
+        default:
+            //pc.printf("Unexpected callback %d\r\n", cmd);
+            return file_not_found;
+            //break;
+    }
+    return noerror;
+}
+
+RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h)
+{
+    BITMAPFILEHEADER BMP_Header;
+    BITMAPINFOHEADER BMP_Info;
+    uint8_t * lineBuffer = NULL;
+    color_t * pixelBuffer = NULL;
+    color_t * pixelBuffer2 = NULL;
+    
+    INFO("(%d,%d) - (%d,%d) %s", x,y,w,h,Name_BMP);
+    if (x >= 0 && x < width()
+            && y >= 0 && y < height()
+            && w > 0 && x + w <= width()
+            && h > 0 && y + h <= height()) {
+
+        BMP_Header.bfType = BF_TYPE;
+        BMP_Header.bfSize = (w * h * sizeof(RGBQUAD)) + sizeof(BMP_Header) + sizeof(BMP_Header);
+        BMP_Header.bfReserved1 = 0;
+        BMP_Header.bfReserved2 = 0;
+        BMP_Header.bfOffBits = sizeof(BMP_Header) + sizeof(BMP_Header);
+
+        BMP_Info.biSize = sizeof(BMP_Info);
+        BMP_Info.biWidth = w;
+        BMP_Info.biHeight = h;
+        BMP_Info.biPlanes = 1;
+        BMP_Info.biBitCount = 24;
+        BMP_Info.biCompression = BI_RGB;
+        BMP_Info.biSizeImage = 0;
+        BMP_Info.biXPelsPerMeter = 0;
+        BMP_Info.biYPelsPerMeter = 0;
+        BMP_Info.biClrUsed = 0;
+        BMP_Info.biClrImportant = 0;
+
+        // Allocate the memory we need to proceed
+        int lineBufSize = ((24 * w + 7)/8);
+        lineBuffer = (uint8_t *)malloc(lineBufSize);
+        if (lineBuffer == NULL) {
+            ERR("Not enough RAM for PrintScreen lineBuffer");
+            return(not_enough_ram);
+        }
+
+        #define DOUBLEBUF /* one larger buffer instead of two */
+        
+        #ifdef DOUBLEBUF
+        // In the "#else", pixelBuffer2 malloc returns a value, 
+        // but is actually causing a failure later. 
+        // This test helps determine if it is truly out of memory,
+        // or if malloc is broken.
+        pixelBuffer = (color_t *)malloc(2 * w * sizeof(color_t));
+        pixelBuffer2 = pixelBuffer + (w * sizeof(color_t));
+        #else
+        pixelBuffer = (color_t *)malloc(w * sizeof(color_t));
+        pixelBuffer2 = (color_t *)malloc(w * sizeof(color_t));
+        #endif
+        if (pixelBuffer == NULL || pixelBuffer2 == NULL) {
+            ERR("Not enough RAM for pixelBuffer");
+            #ifndef DOUBLEBUF
+            if (pixelBuffer2)
+                free(pixelBuffer2);
+            #endif
+            if (pixelBuffer)
+                free(pixelBuffer);
+            free(lineBuffer);
+            if (pixelBuffer)
+                free(pixelBuffer);
+            return(not_enough_ram);
+        }
+
+        // Get the file primed...
+        privateCallback(OPEN, (uint8_t *)&BMP_Header.bfSize, 4);
+
+        // Be optimistic - don't check for errors.
+        HexDump("BMP_Header", (uint8_t *)&BMP_Header, sizeof(BMP_Header));        
+        //fwrite(&BMP_Header, sizeof(char), sizeof(BMP_Header), Image);
+        privateCallback(WRITE, (uint8_t *)&BMP_Header, sizeof(BMP_Header));
+
+        HexDump("BMP_Info", (uint8_t *)&BMP_Info, sizeof(BMP_Info));
+        //fwrite(&BMP_Info, sizeof(char), sizeof(BMP_Info), Image);
+        privateCallback(WRITE, (uint8_t *)&BMP_Info, sizeof(BMP_Info));
+
+        //color_t transparency = GetBackgroundTransparencyColor();
+        LayerMode_T ltpr0 = GetLayerMode();
+
+        uint16_t prevLayer = GetDrawingLayer();
+        // If only one of the layers is visible, select that layer
+        switch(ltpr0) {
+            case ShowLayer0:
+                SelectDrawingLayer(0);
+                break;
+            case ShowLayer1:
+                SelectDrawingLayer(1);
+                break;
+            default:
+                break;
+        }
+
+        // Read the display from the last line toward the top
+        // so we can write the file in one pass.
+        for (int j = h - 1; j >= 0; j--) {
+            if (ltpr0 >= 2)             // Need to combine the layers...
+                SelectDrawingLayer(0);  // so read layer 0 first
+            // Read one line of pixels to a local buffer
+            if (getPixelStream(pixelBuffer, w, x,y+j) != noerror) {
+                ERR("getPixelStream error, and no recovery handler...");
+            }
+            if (ltpr0 >= 2) {           // Need to combine the layers...
+                SelectDrawingLayer(1);  // so read layer 1 next
+                if (getPixelStream(pixelBuffer2, w, x,y+j) != noerror) {
+                    ERR("getPixelStream error, and no recovery handler...");
+                }
+            }
+            INFO("1st Color: %04X", pixelBuffer[0]);
+            HexDump("Raster", (uint8_t *)pixelBuffer, w);
+            // Convert the local buffer to RGBQUAD format
+            int lb = 0;
+            for (int i=0; i<w; i++) {
+                RGBQUAD q0 = RGB16ToRGBQuad(pixelBuffer[x+i]);      // Scale to 24-bits
+                RGBQUAD q1 = RGB16ToRGBQuad(pixelBuffer2[x+i]);     // Scale to 24-bits
+                switch (ltpr0) {
+                    case 0:
+                    case 1:
+                    case 2: // lighten-overlay  (@TODO Not supported yet)
+                    case 6: // Floating Windows     (@TODO not sure how to support)
+                    default: // Reserved...
+                        lineBuffer[lb++] = q0.rgbBlue;
+                        lineBuffer[lb++] = q0.rgbGreen;
+                        lineBuffer[lb++] = q0.rgbRed;
+                        break;
+                    case 3: // transparent mode (@TODO Read the background color register for transparent)
+                    case 4: // boolean or
+                        lineBuffer[lb++] = q0.rgbBlue | q1.rgbBlue;
+                        lineBuffer[lb++] = q0.rgbGreen | q1.rgbGreen;
+                        lineBuffer[lb++] = q0.rgbRed | q1.rgbRed;
+                        break;
+                    case 5: // boolean AND
+                        lineBuffer[lb++] = q0.rgbBlue & q1.rgbBlue;
+                        lineBuffer[lb++] = q0.rgbGreen & q1.rgbGreen;
+                        lineBuffer[lb++] = q0.rgbRed & q1.rgbRed;
+                        break;
+                }
+            }
+            if (j == h - 1) {
+                HexDump("Line", lineBuffer, lineBufSize);
+            }
+            // Write to disk
+            //fwrite(lineBuffer, sizeof(char), lb, Image);
+            privateCallback(WRITE, (uint8_t *)lineBuffer, lb);
+        }
+        SelectDrawingLayer(prevLayer);
+        //fclose(Image);
+        privateCallback(CLOSE, NULL, 0);
+        
+        #ifndef DOUBLEBUF
+        if (pixelBuffer2)
+            free(pixelBuffer2);
+        #endif
+        if (pixelBuffer)
+            free(pixelBuffer);
+        free(lineBuffer);
+        if (pixelBuffer)
+            free(pixelBuffer);
+        INFO("Image closed");
+        return noerror;
+    } else {
+        return bad_parameter;
+    }
+}
 
 RetCode_t RA8875::PrintScreen(loc_t x, loc_t y, dim_t w, dim_t h, const char *Name_BMP)
 {