Beispiel #1
0
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;
}
Beispiel #2
0
/**
 * 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);
}