int res_create_theme_display_surface(const char* name, const char* themename, gr_surface* pSurface) { gr_surface surface = NULL; int result = 0; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; *pSurface = NULL; result = open_theme_png(name, themename, &png_ptr, &info_ptr, &width, &height, &channels); if (result < 0) return result; surface = init_display_surface(width, height); if (surface == NULL) { result = -8; goto exit; } unsigned char* p_row = malloc(width * 4); unsigned int y; for (y = 0; y < height; ++y) { png_read_row(png_ptr, p_row, NULL); transform_rgb_to_draw(p_row, surface->data + y * surface->row_bytes, channels, width); } free(p_row); *pSurface = surface; exit: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (result < 0 && surface != NULL) free(surface); return result; }
int res_create_display_surface(const char *name, gr_surface *pSurface) { int result = 0; unsigned int y; unsigned char *p_row; gr_surface surface = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; FILE *fp = NULL; *pSurface = NULL; result = open_png(name, &png_ptr, &info_ptr, &fp, &width, &height, &channels); if (result < 0) return result; if (!(surface = init_display_surface(width, height))) { result = -8; goto exit; } /* TODO: check for error */ p_row = malloc(width * 4); for (y = 0; y < height; y++) { png_read_row(png_ptr, p_row, NULL); transform_rgb_to_draw(p_row, surface->data + y * surface->row_bytes, channels, width); } free(p_row); *pSurface = surface; exit: close_png(&png_ptr, &info_ptr, fp); if (result < 0 && surface != NULL) free(surface); return result; }
int res_create_surface_png(const char* name, gr_surface* pSurface) { GGLSurface* surface = NULL; int result = 0; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; FILE* fp; *pSurface = NULL; result = open_png(name, &png_ptr, &info_ptr, &width, &height, &channels, &fp); if (result < 0) return result; surface = init_display_surface(width, height); if (surface == NULL) { result = -8; goto exit; } unsigned char* p_row = malloc(width * 4); unsigned int y; for (y = 0; y < height; ++y) { png_read_row(png_ptr, p_row, NULL); transform_rgb_to_draw(p_row, surface->data + y * width * 4, channels, width); } free(p_row); if (channels == 3) surface->format = GGL_PIXEL_FORMAT_RGBX_8888; else surface->format = GGL_PIXEL_FORMAT_RGBA_8888; *pSurface = (gr_surface) surface; exit: fclose(fp); png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (result < 0 && surface != NULL) free(surface); return result; }
// Scale image function int res_scale_surface(gr_surface source, gr_surface* destination, float scale_w, float scale_h) { GGLContext *gl = NULL; GGLSurface* sc_mem_surface = NULL; *destination = NULL; GGLSurface *surface = (GGLSurface*)source; int w = gr_get_width(source), h = gr_get_height(source); int sx = 0, sy = 0, dx = 0, dy = 0; float dw = (float)w * scale_w; float dh = (float)h * scale_h; // Create a new surface that is the appropriate size sc_mem_surface = init_display_surface((int)dw, (int)dh); if (!sc_mem_surface) { printf("gr_scale_surface failed to init_display_surface\n"); return -1; } sc_mem_surface->format = surface->format; // Initialize the context gglInit(&gl); gl->colorBuffer(gl, sc_mem_surface); gl->activeTexture(gl, 0); // Enable or disable blending based on source surface format if (surface->format == GGL_PIXEL_FORMAT_RGBX_8888) { gl->disable(gl, GGL_BLEND); } else { gl->enable(gl, GGL_BLEND); gl->blendFunc(gl, GGL_ONE, GGL_ZERO); } // Bind our source surface to the context gl->bindTexture(gl, surface); // Deal with the scaling gl->texParameteri(gl, GGL_TEXTURE_2D, GGL_TEXTURE_MIN_FILTER, GGL_LINEAR); gl->texParameteri(gl, GGL_TEXTURE_2D, GGL_TEXTURE_MAG_FILTER, GGL_LINEAR); gl->texParameteri(gl, GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_S, GGL_CLAMP); gl->texParameteri(gl, GGL_TEXTURE_2D, GGL_TEXTURE_WRAP_T, GGL_CLAMP); gl->texEnvi(gl, GGL_TEXTURE_ENV, GGL_TEXTURE_ENV_MODE, GGL_REPLACE); gl->texGeni(gl, GGL_S, GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); gl->texGeni(gl, GGL_T, GGL_TEXTURE_GEN_MODE, GGL_AUTOMATIC); gl->enable(gl, GGL_TEXTURE_2D); int32_t grad[8]; memset(grad, 0, sizeof(grad)); // s, dsdx, dsdy, scale, t, dtdx, dtdy, tscale <- this is wrong! // This api uses block floating-point for S and T texture coordinates. // All values are given in 16.16, scaled by 'scale'. In other words, // set scale to 0, for 16.16 values. // s, dsdx, dsdy, t, dtdx, dtdy, sscale, tscale float dsdx = (float)w / dw; float dtdy = (float)h / dh; grad[0] = ((float)sx - (dsdx * dx)) * 65536; grad[1] = dsdx * 65536; grad[3] = ((float)sy - (dtdy * dy)) * 65536; grad[5] = dtdy * 65536; // printf("blit: w=%d h=%d dx=%d dy=%d dw=%f dh=%f dsdx=%f dtdy=%f s0=%x dsdx=%x t0=%x dtdy=%x\n", // w, h, dx, dy, dw, dh, dsdx, dtdy, grad[0], grad[1], grad[3], grad[5]); gl->texCoordGradScale8xv(gl, 0 /*tmu*/, grad); // draw / scale the source surface to our target context gl->recti(gl, dx, dy, dx + dw, dy + dh); gglUninit(gl); gl = NULL; // put the scaled surface in our destination *destination = (gr_surface*) sc_mem_surface; // free memory used in the source res_free_surface(source); source = NULL; return 0; }
int res_create_theme_multi_display_surface(const char* name, const char* themename, int* frames, gr_surface** pSurface) { gr_surface* surface = NULL; int result = 0; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels; int i; *pSurface = NULL; *frames = -1; result = open_theme_png(name, themename, &png_ptr, &info_ptr, &width, &height, &channels); if (result < 0) return result; *frames = 1; png_textp text; int num_text; if (png_get_text(png_ptr, info_ptr, &text, &num_text)) { for (i = 0; i < num_text; ++i) { if (text[i].key && strcmp(text[i].key, "Frames") == 0 && text[i].text) { *frames = atoi(text[i].text); break; } } printf(" found frames = %d\n", *frames); } if (height % *frames != 0) { printf("bad height (%d) for frame count (%d)\n", height, *frames); result = -9; goto exit; } surface = malloc(*frames * sizeof(gr_surface)); if (surface == NULL) { result = -8; goto exit; } for (i = 0; i < *frames; ++i) { surface[i] = init_display_surface(width, height / *frames); if (surface[i] == NULL) { result = -8; goto exit; } } unsigned char* p_row = malloc(width * 4); unsigned int y; for (y = 0; y < height; ++y) { png_read_row(png_ptr, p_row, NULL); int frame = y % *frames; unsigned char* out_row = surface[frame]->data + (y / *frames) * surface[frame]->row_bytes; transform_rgb_to_draw(p_row, out_row, channels, width); } free(p_row); *pSurface = (gr_surface*) surface; exit: png_destroy_read_struct(&png_ptr, &info_ptr, NULL); if (result < 0) { if (surface) { for (i = 0; i < *frames; ++i) { if (surface[i]) free(surface[i]); } free(surface); } } return result; }
int res_create_multi_display_surface(const char *name, int *frames, gr_surface **pSurface) { int i, result = 0, num_text; unsigned int y; unsigned char *p_row; gr_surface *surface = NULL; png_structp png_ptr = NULL; png_infop info_ptr = NULL; png_uint_32 width, height; png_byte channels = 0; png_textp text; FILE *fp = NULL; *pSurface = NULL; *frames = -1; result = open_png(name, &png_ptr, &info_ptr, &fp, &width, &height, &channels); if (result < 0) return result; *frames = 1; if (png_get_text(png_ptr, info_ptr, &text, &num_text)) { for (i = 0; i < num_text; i++) if (text[i].key && !strcmp(text[i].key, "Frames") && text[i].text) { *frames = atoi(text[i].text); break; } printf(" found frames = %d\n", *frames); } if (height % *frames != 0) { printf("bad height (%ld) for frame count (%d)\n", (long)height, *frames); result = -9; goto exit; } if (!(surface = malloc(*frames * sizeof(gr_surface)))) { result = -8; goto exit; } for (i = 0; i < *frames; i++) { surface[i] = init_display_surface(width, height / *frames); if (!surface[i]) { result = -8; goto exit; } } /* TODO: Check for error */ p_row = malloc(width * 4); for (y = 0; y < height; y++) { int frame = y % *frames; unsigned char *out_row; png_read_row(png_ptr, p_row, NULL); out_row = surface[frame]->data + (y / *frames) * surface[frame]->row_bytes; transform_rgb_to_draw(p_row, out_row, channels, width); } free(p_row); *pSurface = (gr_surface *)surface; exit: close_png(&png_ptr, &info_ptr, fp); if (result < 0) if (surface) { for (i = 0; i < *frames; i++) if (surface[i]) free(surface[i]); free(surface); } return result; }