static VALUE Game_update_screen(VALUE self) { const Game* game; Data_Get_Struct(self, Game, game); CheckDisposed(game); volatile VALUE rbScreen = game->screen; const Texture* texture; Data_Get_Struct(rbScreen, Texture, texture); strb_CheckDisposedTexture(texture); const Pixel* src = texture->pixels; SDL_Surface* sdlScreenBuffer = game->sdlScreenBuffer; SDL_LockSurface(sdlScreenBuffer); Pixel* dst = (Pixel*)sdlScreenBuffer->pixels; const int screenPadding = sdlScreenBuffer->pitch / sdlScreenBuffer->format->BytesPerPixel - sdlScreenBuffer->w; const int textureWidth = texture->width; const int textureHeight = texture->height; const int heightPadding = sdlScreenBuffer->w - texture->width + screenPadding; for (int j = 0; j < textureHeight; j++, dst += heightPadding) { for (int i = 0; i < textureWidth; i++, src++, dst++) { const uint8_t alpha = src->color.alpha; if (alpha == 255) { *dst = *src; } else if (alpha) { dst->color.red = DIV255(src->color.red * alpha); dst->color.green = DIV255(src->color.green * alpha); dst->color.blue = DIV255(src->color.blue * alpha); } else { dst->color.red = 0; dst->color.green = 0; dst->color.blue = 0; } } } SDL_UnlockSurface(sdlScreenBuffer); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, sdlScreenBuffer->w, sdlScreenBuffer->h, 0, GL_BGRA, GL_UNSIGNED_BYTE, sdlScreenBuffer->pixels); glClear(GL_COLOR_BUFFER_BIT); glColor3f(1.0, 1.0, 1.0); glBegin(GL_QUADS); { int x1, y1, x2, y2; if (!game->isFullscreen) { x1 = 0; y1 = 0; x2 = game->sdlScreen->w; y2 = game->sdlScreen->h; } else { x1 = (game->sdlScreen->w - textureWidth) / 2; y1 = (game->sdlScreen->h - textureHeight) / 2; x2 = x1 + textureWidth; y2 = y1 + textureHeight; } const double tu = (double)textureWidth / sdlScreenBuffer->w; const double tv = (double)textureHeight / sdlScreenBuffer->h; glTexCoord2f(0.0, 0.0); glVertex3i(x1, y1, 0); glTexCoord2f(tu, 0.0); glVertex3i(x2, y1, 0); glTexCoord2f(tu, tv); glVertex3i(x2, y2, 0); glTexCoord2f(0.0, tv); glVertex3i(x1, y2, 0); } glEnd(); SDL_GL_SwapBuffers(); return Qnil; }
/** * create a bitmap from jpeg content. */ static struct bitmap * jpeg_cache_convert(struct content *c) { uint8_t *source_data; /* Jpeg source data */ unsigned long source_size; /* length of Jpeg source data */ struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; jmp_buf setjmp_buffer; unsigned int height; unsigned int width; struct bitmap * volatile bitmap = NULL; uint8_t * volatile pixels = NULL; size_t rowstride; struct jpeg_source_mgr source_mgr = { 0, 0, nsjpeg_init_source, nsjpeg_fill_input_buffer, nsjpeg_skip_input_data, jpeg_resync_to_restart, nsjpeg_term_source }; /* obtain jpeg source data and perfom minimal sanity checks */ source_data = (uint8_t *)content__get_source_data(c, &source_size); if ((source_data == NULL) || (source_size < MIN_JPEG_SIZE)) { return NULL; } /* setup a JPEG library error handler */ cinfo.err = jpeg_std_error(&jerr); jerr.error_exit = nsjpeg_error_exit; jerr.output_message = nsjpeg_error_log; /* handler for fatal errors during decompression */ if (setjmp(setjmp_buffer)) { jpeg_destroy_decompress(&cinfo); return bitmap; } cinfo.client_data = &setjmp_buffer; jpeg_create_decompress(&cinfo); /* setup data source */ source_mgr.next_input_byte = source_data; source_mgr.bytes_in_buffer = source_size; cinfo.src = &source_mgr; /* read JPEG header information */ jpeg_read_header(&cinfo, TRUE); /* set output processing parameters */ if (cinfo.jpeg_color_space == JCS_CMYK || cinfo.jpeg_color_space == JCS_YCCK) { cinfo.out_color_space = JCS_CMYK; } else { cinfo.out_color_space = JCS_RGB; } cinfo.dct_method = JDCT_ISLOW; /* commence the decompression, output parameters now valid */ jpeg_start_decompress(&cinfo); width = cinfo.output_width; height = cinfo.output_height; /* create opaque bitmap (jpegs cannot be transparent) */ bitmap = guit->bitmap->create(width, height, BITMAP_NEW | BITMAP_OPAQUE); if (bitmap == NULL) { /* empty bitmap could not be created */ jpeg_destroy_decompress(&cinfo); return NULL; } pixels = guit->bitmap->get_buffer(bitmap); if (pixels == NULL) { /* bitmap with no buffer available */ guit->bitmap->destroy(bitmap); jpeg_destroy_decompress(&cinfo); return NULL; } /* Convert scanlines from jpeg into bitmap */ rowstride = guit->bitmap->get_rowstride(bitmap); do { JSAMPROW scanlines[1]; scanlines[0] = (JSAMPROW) (pixels + rowstride * cinfo.output_scanline); jpeg_read_scanlines(&cinfo, scanlines, 1); if (cinfo.out_color_space == JCS_CMYK) { int i; for (i = width - 1; 0 <= i; i--) { /* Trivial inverse CMYK -> RGBA */ const int c = scanlines[0][i * 4 + 0]; const int m = scanlines[0][i * 4 + 1]; const int y = scanlines[0][i * 4 + 2]; const int k = scanlines[0][i * 4 + 3]; const int ck = c * k; const int mk = m * k; const int yk = y * k; #define DIV255(x) ((x) + 1 + ((x) >> 8)) >> 8 scanlines[0][i * 4 + 0] = DIV255(ck); scanlines[0][i * 4 + 1] = DIV255(mk); scanlines[0][i * 4 + 2] = DIV255(yk); scanlines[0][i * 4 + 3] = 0xff; #undef DIV255 } } else { #if RGB_RED != 0 || RGB_GREEN != 1 || RGB_BLUE != 2 || RGB_PIXELSIZE != 4 /* Missmatch between configured libjpeg pixel format and * NetSurf pixel format. Convert to RGBA */ int i; for (i = width - 1; 0 <= i; i--) { int r = scanlines[0][i * RGB_PIXELSIZE + RGB_RED]; int g = scanlines[0][i * RGB_PIXELSIZE + RGB_GREEN]; int b = scanlines[0][i * RGB_PIXELSIZE + RGB_BLUE]; scanlines[0][i * 4 + 0] = r; scanlines[0][i * 4 + 1] = g; scanlines[0][i * 4 + 2] = b; scanlines[0][i * 4 + 3] = 0xff; } #endif } } while (cinfo.output_scanline != cinfo.output_height); guit->bitmap->modified(bitmap); jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); return bitmap; }
mlib_status mlib_ZoomBlendEdge( mlib_image *dst, const mlib_image *src, mlib_work_image * param, mlib_filter filter, mlib_edge edge, mlib_s32 alp_ind) { mlib_s32 schan, dchan, t_ind, bsize, i, j, k; mlib_blend blend = param->blend; mlib_edge_box *edges = param->edges; mlib_u8 *buff, *pbuff; schan = mlib_ImageGetChannels(src); dchan = mlib_ImageGetChannels(dst); t_ind = (schan - 3) + 2 * (dchan - 3); bsize = 0; for (i = 0; i < 4; i++) { if (edges[i].w < 0) edges[i].w = 0; if (edges[i].h < 0) edges[i].h = 0; bsize += edges[i].w * edges[i].h; } if (!bsize) return (MLIB_SUCCESS); bsize *= schan; mlib_ImageCopy_na((void *)edges, (void *)&(param->edges_blend), sizeof (param->edges_blend)); pbuff = buff = __mlib_malloc(bsize); if (buff == NULL) return (MLIB_FAILURE); for (i = 0; i < 4; i++) { mlib_s32 dlb = schan * edges[i].w; edges[i].dp = pbuff; edges[i].dlb = dlb; pbuff += dlb * edges[i].h; } MLIB_EDGE_RULES; for (k = 0; k < 4; k++) { mlib_s32 ww = edges[k].w; mlib_s32 hh = edges[k].h; mlib_s32 slb = edges[k].dlb; mlib_s32 dlb = param->edges_blend[k].dlb; mlib_u8 *sp = edges[k].dp; mlib_u8 *dp = param->edges_blend[k].dp; if (ww == 0 || hh == 0) continue; if (alp_ind == -1) { if (schan == 4) sp++; if (dchan == 4) dp++; } /* 33 */ if (t_ind == 0) { FP_TYPE a0 = (param->alpha); for (j = 0; j < hh; j++) { for (i = 0; i < 3 * ww; i++) { BLEND33(dp[i], sp[i]); } sp += slb; dp += dlb; } } else if (t_ind == 1) { /* 43 */ FP_TYPE a0 = (param->alpha), dalpha = a0; if (edge == MLIB_EDGE_SRC_EXTEND || edge == MLIB_EDGE_SRC_EXTEND_INDEF) { FP_TYPE a1; if (blend == MLIB_BLEND_GTK_SRC) { for (j = 0; j < hh; j++) { for (i = 0; i < ww; i++) { STORE(dp[3 * i], sp[4 * i]); STORE(dp[3 * i + 1], sp[4 * i + 1]); STORE(dp[3 * i + 2], sp[4 * i + 2]); } sp += slb; dp += dlb; } } else { for (j = 0; j < hh; j++) { for (i = 0; i < ww; i++) { a1 = (255*255) - dalpha * sp[4 * i + alp_ind]; BLEND43(dp[3 * i], sp[4 * i]); BLEND43(dp[3 * i + 1], sp[4 * i + 1]); BLEND43(dp[3 * i + 2], sp[4 * i + 2]); } sp += slb; dp += dlb; } } } else { if (blend == MLIB_BLEND_GTK_SRC) { for (j = 0; j < hh; j++) { for (i = 0; i < ww; i++) { mlib_s64 out, in; a0 = sp[4 * i + alp_ind]; in = a0 * sp[4 * i]; DIV255(out, in); dp[3 * i] = (mlib_u8)(out); in = a0 * sp[4 * i + 1]; DIV255(out, in); dp[3 * i + 1] = (mlib_u8)(out); in = a0 * sp[4 * i + 2]; DIV255(out, in); dp[3 * i + 2] = (mlib_u8)(out); } sp += slb; dp += dlb; } } else { for (j = 0; j < hh; j++) { for (i = 0; i < ww; i++) { a0 = dalpha * sp[4 * i + alp_ind]; BLEND33_dalpha( dp[3 * i], sp[4 * i]); BLEND33_dalpha( dp[3 * i + 1], sp[4 * i + 1]); BLEND33_dalpha( dp[3 * i + 2], sp[4 * i + 2]); } sp += slb; dp += dlb; } } } } else if (t_ind == 2) { /* 34 */ FP_TYPE w0 = (FP_TYPE) param->alpha; FP_TYPE w1s = 255 - w0; w0 = MUL255(w0); FP_TYPE w1, w; if (blend == MLIB_BLEND_GTK_SRC_OVER2) { for (j = 0; j < hh; j++) { for (i = 0; i < ww; i++) { w1 = w1s * dp[4 * i + alp_ind]; w = w0 + w1; if (w < 255) { dp[4 * i + alp_ind] = 0; } else { BLEND34_OVER2(dp[4 * i], sp[3 * i]); BLEND34_OVER2( dp[4 * i + 1], sp[3 * i + 1]); BLEND34_OVER2( dp[4 * i + 2], sp[3 * i + 2]); mlib_s64 out; DIV255(out, w); dp[4 * i + alp_ind] = (mlib_u8)(out); } } sp += slb; dp += dlb; } } else { for (j = 0; j < hh; j++) { for (i = 0; i < ww; i++) { w1 = w1s * dp[4 * i + alp_ind]; w = w0 + w1; if (w < 255) { dp[4 * i] = 0; dp[4 * i + 1] = 0; dp[4 * i + 2] = 0; dp[4 * i + alp_ind] = 0; } else { BLEND34z(dp[4 * i], sp[3 * i]); BLEND34z(dp[4 * i + 1], sp[3 * i + 1]); BLEND34z(dp[4 * i + 2], sp[3 * i + 2]); mlib_s64 out; DIV255(out, w); dp[4 * i + alp_ind] = (mlib_u8)(out); } } sp += slb; dp += dlb; } } } else if (t_ind == 3) { /* 44 */ FP_TYPE dalpha0 = (FP_TYPE) param->alpha, dalpha = dalpha0; FP_TYPE w0, w1, w; if (edge == MLIB_EDGE_SRC_EXTEND || edge == MLIB_EDGE_SRC_EXTEND_INDEF) { for (j = 0; j < hh; j++) { if (blend == MLIB_BLEND_GTK_SRC) { for (i = 0; i < ww; i++) { w = sp[4 * i + alp_ind]; if (w == 0) { dp[4 * i] = 0; dp[4 * i + 1] = 0; dp[4 * i + 2] = 0; dp[4 * i + alp_ind] = 0; } else { BLEND_GTK_SRC( dp[4 * i], sp[4 * i]); BLEND_GTK_SRC( dp[4 * i + 1], sp[4 * i + 1]); BLEND_GTK_SRC( dp[4 * i + 2], sp[4 * i + 2]); dp[4 * i + alp_ind] = sp[4 * i + alp_ind]; } } } else if (blend == MLIB_BLEND_GTK_SRC_OVER2) { for (i = 0; i < ww; i++) { w0 = dalpha * sp[4 * i + alp_ind]; w1 = ((255*255) - w0) * dp[4 * i + alp_ind]; w0 = MUL255(w0); w = w0 + w1; if (w < (255*255)) { BLEND44_A( dp[4 * i]); BLEND44_A( dp[4 * i + 1]); BLEND44_A( dp[4 * i + 2]); dp[4 * i + alp_ind] = 0; } else { BLEND44( dp[4 * i], sp[4 * i]); BLEND44( dp[4 * i + 1], sp[4 * i + 1]); BLEND44( dp[4 * i + 2], sp[4 * i + 2]); mlib_s64 out; DIV65025(out, w); dp[4 * i + alp_ind] = (mlib_u8) (out); } } } else { for (i = 0; i < ww; i++) { w0 = dalpha * sp[4 * i + alp_ind]; w1 = ((255*255) - w0) * dp[4 * i + alp_ind]; w0 = MUL255(w0); w = w0 + w1; if (w < (255*255)) { dp[4 * i] = 0; dp[4 * i + 1] = 0; dp[4 * i + 2] = 0; dp[4 * i + alp_ind] = 0; } else { BLEND44z( dp[4 * i], sp[4 * i]); BLEND44z( dp[4 * i + 1], sp[4 * i + 1]); BLEND44z( dp[4 * i + 2], sp[4 * i + 2]); mlib_s64 out; DIV65025(out, w); dp[4 * i + alp_ind] = (mlib_u8) (out); } } } sp += slb; dp += dlb; } } else { for (j = 0; j < hh; j++) { if (blend == MLIB_BLEND_GTK_SRC) { for (i = 0; i < ww; i++) { dp[4 * i] = sp[4 * i]; dp[4 * i + 1] = sp[4 * i + 1]; dp[4 * i + 2] = sp[4 * i + 2]; dp[4 * i + alp_ind] = sp[4 * i + alp_ind]; } } else if (blend == MLIB_BLEND_GTK_SRC_OVER2) { for (i = 0; i < ww; i++) { w0 = dalpha * sp[4 * i + alp_ind]; w1 = ((255*255) - w0) * dp[4 * i + alp_ind]; w0 = MUL255(w0); w = w0 + w1; if (w < (255*255)) { dp[4 * i + alp_ind] = 0; } else { BLEND34_OVER2( dp[4 * i], sp[4 * i]); BLEND34_OVER2( dp[4 * i + 1], sp[4 * i + 1]); BLEND34_OVER2( dp[4 * i + 2], sp[4 * i + 2]); mlib_s64 out; DIV65025(out, w); dp[4 * i + alp_ind] = (mlib_u8) (out); } } } else { for (i = 0; i < ww; i++) { w0 = dalpha * sp[4 * i + alp_ind]; w1 = ((255*255) - w0) * dp[4 * i + alp_ind]; w0 = MUL255(w0); w = w0 + w1; if (w < (255*255)) { dp[4 * i] = 0; dp[4 * i + 1] = 0; dp[4 * i + 2] = 0; dp[4 * i + alp_ind] = 0; } else { BLEND34z( dp[4 * i], sp[4 * i]); BLEND34z( dp[4 * i + 1], sp[4 * i + 1]); BLEND34z( dp[4 * i + 2], sp[4 * i + 2]); mlib_s64 out; DIV65025(out, w); dp[4 * i + alp_ind] = (mlib_u8) (out); } } } sp += slb; dp += dlb; } } } } __mlib_free(buff); return (MLIB_SUCCESS); }