예제 #1
0
/* Create a masked surface from the given transparent sprite and mask.
   The sprite must be at least as wide as the mask plus mask offset. */
static SDL_Surface *
create_masked_transp_surface(const sprite_t *sprite, const sprite_t *mask, int mask_off)
{
	void *s_data = (uint8_t *)sprite + sizeof(sprite_t);

	size_t s_width = le16toh(sprite->w);
	size_t s_height = le16toh(sprite->h);

	/* Unpack */
	size_t unpack_size = s_width * s_height;
	uint8_t *unpack = calloc(unpack_size, sizeof(uint8_t));
	if (unpack == NULL) abort();

	gfx_unpack_transparent_sprite(unpack, s_data, unpack_size, 0);

	size_t m_width = le16toh(mask->w);
	size_t m_height = le16toh(mask->h);

	uint8_t *s_copy = calloc(m_width * m_height, sizeof(uint8_t));
	if (s_copy == NULL) abort();

	size_t to_copy = m_width * min(m_height, s_height);
	uint8_t *copy_dest = s_copy;
	uint8_t *copy_src = unpack + mask_off;
	while (to_copy) {
		memcpy(copy_dest, copy_src, m_width * sizeof(uint8_t));
		to_copy -= m_width;
		copy_dest += m_width;
		copy_src += s_width;
	}

	free(unpack);

	/* Mask */
	void *m_data = (uint8_t *)mask + sizeof(sprite_t);

	/* Unpack mask */
	size_t m_unpack_size = m_width * m_height;
	uint8_t *m_unpack = calloc(m_unpack_size, sizeof(uint8_t));
	if (m_unpack == NULL) abort();

	gfx_unpack_mask_sprite(m_unpack, m_data, m_unpack_size);

	/* Fill alpha value from mask data */
	for (int y = 0; y < m_height; y++) {
		for (int x = 0; x < m_width; x++) {
			if (!m_unpack[y*m_width+x]) {
				*(s_copy + y * m_width + x) = 0;
			}
		}
	}

	free(m_unpack);

	SDL_Surface *surf = create_surface_from_data(s_copy, m_width, m_height, 1);

	free(s_copy);

	return surf;
}
예제 #2
0
surface_t *
skia_draw_masked_sprite(const sprite_t *sprite, int x, int y, const sprite_t *mask, surface_t *surface, frame_t *dest)
{
//  LOGI("skia_draw_masked_sprite x=%d y=%d", x, y);

    if (dest == NULL) {
        LOGE("skia_draw_masked_sprite: dest is NULL");
        return 0;
    }

    if (dest->skCanvas == NULL) {
        LOGE("skia_draw_masked_sprite: dest->skCanvas is NULL");
        return 0;
    }

    size_t m_width = le16toh(mask->w);
    size_t m_height = le16toh(mask->h);

    size_t s_width = le16toh(sprite->w);
    size_t s_height = le16toh(sprite->h);

    SkAutoMalloc auto_s_copy (m_width * m_height);
    uint8_t* s_copy = static_cast<uint8_t*>(auto_s_copy.get());
    if (s_copy == NULL) {
        LOGE("skia_draw_masked_sprite: out of memory");
        return 0;
    }

    void *s_data = (uint8_t *)sprite + sizeof(sprite_t);

    size_t to_copy = m_width * m_height;
    size_t s_size = s_width * s_height;
    uint8_t *copy_dest = s_copy;
    while (to_copy) {
        size_t s = to_copy < s_size ? to_copy : s_size;
        memcpy(copy_dest, s_data, s * sizeof(uint8_t));  // copy from beginning again
        to_copy -= s;
        copy_dest += s;
    }


    // Mask
    void *m_data = (uint8_t *)mask + sizeof(sprite_t);

    /* Unpack mask */
    size_t unpack_size = m_width * m_height;
    SkAutoMalloc auto_m_unpack (unpack_size);
    uint8_t* m_unpack = static_cast<uint8_t*>(auto_m_unpack.get());
    if (m_unpack == NULL) {
        LOGE("m_unpack is NULL");
        return 0;
    }

    gfx_unpack_mask_sprite(m_unpack, m_data, unpack_size);

    // Fill alpha value from mask data
    for (int y = 0; y < m_height; y++) {
        for (int x = 0; x < m_width; x++) {
            if (m_unpack[y*m_width+x] == 0) {
                s_copy[y*m_width+x] = 0;
            }
        }
    }

    SkBitmap bitmap;
    bitmap.setConfig(SkBitmap::kIndex8_Config, m_width, m_height);
    bitmap.setPixels(s_copy, g_color_table.get());

    x += le16toh(mask->x);
    y += le16toh(mask->y);

    SkRect src_rect;
    src_rect.fLeft = 0;
    src_rect.fTop = 0;
    src_rect.fRight = SkIntToScalar(m_width);
    src_rect.fBottom = SkIntToScalar(m_height);

    SkRect dst_rect;
    dst_rect.fLeft = x;
    dst_rect.fTop = y;
    dst_rect.fRight = x + SkIntToScalar(m_width);
    dst_rect.fBottom = y + SkIntToScalar(m_height);

    ((SkCanvas*)dest->skCanvas)->drawBitmapRectToRect(bitmap, &src_rect, dst_rect, NULL);

    return 0;
}
예제 #3
0
void
sdl_draw_overlay_sprite(const sprite_t *sprite, int x, int y, int y_off, frame_t *dest)
{
	int r;

	x += le16toh(sprite->x) + dest->clip.x;
	y += le16toh(sprite->y) + dest->clip.y;

	const surface_id_t id = { .sprite = sprite, .mask = NULL, .offset = 0 };
	surface_t **surface = surface_ht_store(&overlay_sprite_cache, &id);
	if (*surface == NULL) {
		*surface = malloc(sizeof(surface_t));
		if (*surface == NULL) abort();

		(*surface)->surf = create_overlay_surface(sprite);
	}

	SDL_Surface *surf = (*surface)->surf;
	SDL_Rect src_rect = { 0, y_off, surf->w, surf->h - y_off };
	SDL_Rect dest_rect = { x, y + y_off, 0, 0 };

	SDL_SetClipRect(dest->surf, &dest->clip);

	/* Blit sprite */
	r = SDL_BlitSurface(surf, &src_rect, dest->surf, &dest_rect);
	if (r < 0) {
		LOGE("sdl-video", "BlitSurface error: %s.", SDL_GetError());
	}

#if 0
	/* Bounding box */
	sdl_draw_rect(x, y + y_off, surf->w, surf->h - y_off, 1, dest);
#endif
}

static SDL_Surface *
create_masked_surface(const sprite_t *sprite, const sprite_t *mask)
{
	size_t m_width = le16toh(mask->w);
	size_t m_height = le16toh(mask->h);

	size_t s_width = le16toh(sprite->w);
	size_t s_height = le16toh(sprite->h);

	void *s_data = (uint8_t *)sprite + sizeof(sprite_t);

	uint8_t *s_copy = malloc(m_width * m_height * sizeof(uint8_t));
	if (s_copy == NULL) abort();

	size_t to_copy = m_width * m_height;
	uint8_t *copy_dest = s_copy;
	while (to_copy) {
		size_t s = min(to_copy, s_width * s_height);
		memcpy(copy_dest, s_data, s * sizeof(uint8_t));
		to_copy -= s;
		copy_dest += s;
	}

	/* Mask */
	void *m_data = (uint8_t *)mask + sizeof(sprite_t);

	/* Unpack mask */
	size_t unpack_size = m_width * m_height;
	uint8_t *m_unpack = calloc(unpack_size, sizeof(uint8_t));
	if (m_unpack == NULL) abort();

	gfx_unpack_mask_sprite(m_unpack, m_data, unpack_size);

	/* Fill alpha value from mask data */
	for (int y = 0; y < m_height; y++) {
		for (int x = 0; x < m_width; x++) {
			if (!m_unpack[y*m_width+x]) {
				*(s_copy + y * m_width + x) = 0;
			}
		}
	}

	free(m_unpack);

	SDL_Surface *surf = create_surface_from_data(s_copy, (int)m_width, (int)m_height, 1);

	free(s_copy);

	return surf;
}