| /* |
| * Copyright (C) 2007 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "minui.h" |
| #include "bmp.h" |
| #include "minui_log.h" |
| |
| #define SURFACE_DATA_ALIGNMENT 8 |
| |
| static grsurface *malloc_surface(size_t data_size) |
| { |
| size_t size; |
| unsigned char *temp; |
| grsurface *surface; |
| |
| size = sizeof(grsurface) + data_size + SURFACE_DATA_ALIGNMENT; |
| temp = (unsigned char*)(malloc(size)); |
| memset(temp, 0x0, size); |
| if (temp == NULL) |
| return NULL; |
| surface = (grsurface *)(temp); |
| surface->data = temp + sizeof(grsurface) + |
| (SURFACE_DATA_ALIGNMENT - (sizeof(grsurface) % SURFACE_DATA_ALIGNMENT)); |
| return surface; |
| } |
| |
| #ifdef NOT_USED |
| // "display" surfaces are transformed into the framebuffer's required |
| // pixel format (currently only RGBX is supported) at load time, so |
| // gr_blit() can be nothing more than a memcpy() for each row. The |
| // next two functions are the only ones that know anything about the |
| // framebuffer pixel format; they need to be modified if the |
| // framebuffer format changes (but nothing else should). |
| |
| // Allocate and return a grsurface* sufficient for storing an image of |
| // the indicated size in the framebuffer pixel format. |
| static grsurface *init_display_surface(unsigned int width, unsigned int height) |
| { |
| grsurface *surface = malloc_surface(width * height * 4); |
| |
| if (!surface) |
| return NULL; |
| |
| surface->width = width; |
| surface->height = height; |
| surface->row_bytes = width * 4; |
| surface->pixel_bytes = 4; |
| |
| return surface; |
| } |
| |
| // Copy 'input_row' to 'output_row', transforming it to the |
| // framebuffer pixel format. The input format depends on the value of |
| // 'channels': |
| // |
| // 1 - input is 8-bit grayscale |
| // 3 - input is 24-bit RGB |
| // 4 - input is 32-bit RGBA/RGBX |
| // |
| // 'width' is the number of pixels in the row. |
| static void transform_rgb_to_draw(unsigned char* input_row, |
| unsigned char* output_row, |
| int channels, int width) { |
| int x; |
| unsigned char* ip = input_row; |
| unsigned char* op = output_row; |
| |
| switch (channels) { |
| case 1: |
| // expand gray level to RGBX |
| for (x = 0; x < width; ++x) { |
| *op++ = *ip; |
| *op++ = *ip; |
| *op++ = *ip; |
| *op++ = 0xff; |
| ip++; |
| } |
| break; |
| |
| case 3: |
| // expand RGBA to RGBX |
| for (x = 0; x < width; ++x) { |
| *op++ = *ip++; |
| *op++ = *ip++; |
| *op++ = *ip++; |
| *op++ = 0xff; |
| } |
| break; |
| |
| case 4: |
| // copy RGBA to RGBX |
| memcpy(output_row, input_row, width*4); |
| break; |
| default: |
| ui_logd("wrong channels.\n"); |
| break; |
| } |
| } |
| #endif |
| |
| int res_create_display_surface_from_addr(ulong addr, grsurface **psurface) |
| { |
| grsurface *surface = NULL; |
| BITMAPINFOHEADER stbmpinfoheader = {0}; |
| bmpinfo stbmpinfo = {0}; |
| unsigned int width = 0, height = 0; |
| unsigned char *buffer = NULL; |
| int ret = 0; |
| |
| *psurface = NULL; |
| ret = read_bmp_from_addr(addr, &stbmpinfoheader, &buffer); |
| if (ret < 0) { |
| ui_loge("res_create_display_surface failed\n"); |
| return ret; |
| } |
| |
| ui_logd("res_create_display_surface,name = %lx, buffer=%p\n", addr, buffer); |
| ui_logd("stbmpinfoheader.bibitcount =%d\n", stbmpinfoheader.bibitcount); |
| |
| stbmpinfo.bgcolor = 0xff0000; |
| stbmpinfo.fgcolor = 0xffff00; |
| stbmpinfo.width = stbmpinfoheader.biwidth; |
| stbmpinfo.height = stbmpinfoheader.biheight; |
| stbmpinfo.bmpformat = stbmpinfoheader.bibitcount; |
| stbmpinfo.bmpbuf = buffer; |
| if (stbmpinfoheader.bibitcount < 32) |
| stbmpinfoheader.bibitcount = 32; |
| width = stbmpinfoheader.biwidth * stbmpinfoheader.bibitcount >> 3; |
| height = stbmpinfoheader.biheight; |
| |
| surface = malloc_surface(width * height); |
| if (!surface) { |
| ret = -2; |
| goto exit; |
| } |
| |
| surface->width = stbmpinfoheader.biwidth; |
| surface->height = height; |
| surface->row_bytes = width; |
| surface->pixel_bytes = stbmpinfoheader.bibitcount >> 3; |
| |
| ret = load_bmp(&stbmpinfo, surface->data); |
| if (ret < 0) { |
| ret = -3; |
| goto exit; |
| } |
| |
| *psurface = surface; |
| |
| exit: |
| if (ret < 0 && surface) |
| free(surface); |
| return ret; |
| } |
| |
| int res_create_display_surface(const char *name, grsurface **psurface) |
| { |
| grsurface *surface = NULL; |
| BITMAPINFOHEADER stbmpinfoheader = {0}; |
| bmpinfo stbmpinfo = {0}; |
| unsigned int width = 0, height = 0; |
| unsigned char *buffer = NULL; |
| int ret = 0; |
| |
| *psurface = NULL; |
| ret = read_bmp(name, &stbmpinfoheader, &buffer); |
| if (ret < 0) { |
| ui_loge("res_create_display_surface failed\n"); |
| return ret; |
| } |
| |
| ui_logd("res_create_display_surface,name = %s, buffer=%p\n", name, buffer); |
| ui_logd("stbmpinfoheader.bibitcount =%d\n", stbmpinfoheader.bibitcount); |
| |
| stbmpinfo.bgcolor = 0xff0000; |
| stbmpinfo.fgcolor = 0xffff00; |
| stbmpinfo.width = stbmpinfoheader.biwidth; |
| stbmpinfo.height = stbmpinfoheader.biheight; |
| stbmpinfo.bmpformat = stbmpinfoheader.bibitcount; |
| stbmpinfo.bmpbuf = buffer; |
| if (stbmpinfoheader.bibitcount < 32) |
| stbmpinfoheader.bibitcount = 32; |
| width = stbmpinfoheader.biwidth * stbmpinfoheader.bibitcount >> 3; |
| height = stbmpinfoheader.biheight; |
| |
| surface = malloc_surface(width * height); |
| if (surface == NULL) { |
| ret = -2; |
| goto exit; |
| } |
| |
| surface->width = stbmpinfoheader.biwidth; |
| surface->height = height; |
| surface->row_bytes = width; |
| surface->pixel_bytes = stbmpinfoheader.bibitcount >> 3; |
| |
| ret = load_bmp(&stbmpinfo, surface->data); |
| if (ret < 0) { |
| ret = -3; |
| goto exit; |
| } |
| |
| *psurface = surface; |
| |
| exit: |
| if (ret < 0 && surface != NULL) { |
| free(surface); |
| } |
| return ret; |
| } |
| |
| int res_create_alpha_surface(const char *name, grsurface **psurface) |
| { |
| grsurface *surface = NULL; |
| BITMAPINFOHEADER stbmpinfoheader = {0}; |
| bmpinfo stbmpinfo = {0}; |
| unsigned int width = 0, height = 0; |
| unsigned char *buffer = NULL; |
| int ret = 0; |
| |
| *psurface = NULL; |
| ret = read_bmp(name, &stbmpinfoheader, &buffer); |
| if (ret < 0) { |
| return ret; |
| } |
| |
| stbmpinfo.bgcolor = 0xfffffff; |
| stbmpinfo.fgcolor = 0xfffffff; |
| stbmpinfo.width = stbmpinfoheader.biwidth; |
| stbmpinfo.height = stbmpinfoheader.biheight; |
| stbmpinfo.bmpformat = stbmpinfoheader.bibitcount; |
| stbmpinfo.bmpbuf = buffer; |
| width = stbmpinfoheader.biwidth * stbmpinfoheader.bibitcount; |
| height = stbmpinfoheader.biheight; |
| ui_logd("width=%d, height =%d stbmpinfoheader.biwidth=%d, stbmpinfoheader.bibitcount=%d\n", |
| width, height, |
| stbmpinfoheader.biwidth, |
| stbmpinfoheader.bibitcount); |
| |
| surface = malloc_surface(width * height); |
| if (surface == NULL) { |
| ret = -2; |
| goto exit; |
| } |
| |
| surface->width = stbmpinfoheader.biwidth; |
| surface->height = height; |
| surface->row_bytes = width; |
| surface->pixel_bytes = 1; |
| |
| ret = load_bmp(&stbmpinfo, surface->data); |
| if (ret < 0) { |
| ret = -3; |
| goto exit; |
| } |
| |
| *psurface = surface; |
| |
| exit: |
| if (ret < 0 && surface != NULL) { |
| free(surface); |
| } |
| return ret; |
| } |
| |
| void res_free_surface(grsurface *surface) |
| { |
| if (surface) { |
| free(surface); |
| surface = NULL; |
| } |
| } |