static void set_window_icon() { fs_log("setting _NET_WM_ICON from icon images\n"); int max_size = (16 * 16 + 32 * 32 + 48 * 48 + 64 * 64 + 128 * 128) * \ sizeof(unsigned long); // add space for width, height cardinals max_size += 2 * 5 * sizeof(unsigned long); unsigned long *icon_data = (unsigned long *) g_malloc(max_size); unsigned long *op = icon_data; int card_count = 0; int sizes[] = {128, 64, 48, 32, 16, 0}; for(int *size = sizes; *size; size++) { char *rel = g_strdup_printf("icons/hicolor/%dx%d/apps/fs-uae.png", *size, *size); char *path = fs_get_data_file(rel); g_free(rel); if (!path) { fs_log("did not find icon for %dx%d\n", *size, *size); continue; } fs_image *image = fs_image_new_from_file(path); if (!image) { fs_log("could not load icon from %s\n", path); continue; } g_free(path); //printf("%d\n", image->width); int pixel_count = image->width * image->height; unsigned char *p = image->data; *op++ = image->width; *op++ = image->height; for (int i = 0; i < pixel_count; i++) { //*op = 0xffff0000; *op = (((unsigned long) p[3]) << 24) | (p[0] << 16) | (p[1] << 8) | p[2]; p += 4; op++; } card_count += 2 + pixel_count; fs_unref(image); // FIXME } Atom _NET_WM_ICON = XInternAtom(g_display, "_NET_WM_ICON", False); XChangeProperty(g_display, g_window, _NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, (unsigned char *) icon_data, card_count); g_free(icon_data); }
static fs_image *load_font_from_file(const char *path) { if (path == NULL) { fs_emu_warning(_("Could not find font: %s"), path); return NULL; } fs_emu_log("loading image \"%s\"\n", path); fs_image *image = fs_image_new_from_file(path); if (image == NULL) { fs_emu_warning(_("Error loading font: %s"), path); return NULL; } convert_to_premultiplied_alpha(image); return image; }
fs_image *load_font_from_file(const char *name) { char *full_name = g_strconcat(name, ".png", NULL); //char *path = g_build_filename(fs_emu_get_share_dir(), full_name, NULL); char *path = fs_get_program_data_file(full_name); if (path == NULL) { fs_emu_warning("Could not find font %s", full_name); return NULL; } fs_emu_log("loading image \"%s\"\n", path); fs_image *image = fs_image_new_from_file(path); g_free(path); if (image == NULL) { fs_emu_warning("Error loading font from %s", full_name); g_free(full_name); return NULL; } g_free(full_name); // convert to premultiplied alpha if (image->format == FS_IMAGE_FORMAT_RGBA) { int num_pixels = image->width * image->height; unsigned char *pixels = image->data; for (int i = 0; i < num_pixels; i++) { unsigned char alpha = pixels[3]; // should really divide by 255, but 256 is faster... //pixels[0] = ((int) pixels[0]) * alpha / 256; //pixels[1] = ((int) pixels[1]) * alpha / 256; //pixels[2] = ((int) pixels[2]) * alpha / 256; pixels[0] = ((int) pixels[0]) * alpha / 255; pixels[1] = ((int) pixels[1]) * alpha / 255; pixels[2] = ((int) pixels[2]) * alpha / 255; //pixels[0] = (unsigned char) ((pixels[0] * alpha + 0.5) / 255.0); //pixels[1] = (unsigned char) ((pixels[1] * alpha + 0.5) / 255.0); //pixels[2] = (unsigned char) ((pixels[2] * alpha + 0.5) / 255.0); pixels += 4; } } return image; }
fs_emu_texture *fs_emu_texture_new_from_file(const char *name) { char *full_name; char *path; if (fs_path_exists(name)) { full_name = fs_strdup(name); path = fs_strdup(name); } else { full_name = fs_strconcat(name, ".png", NULL); path = fs_get_program_data_file(full_name); if (path == NULL) { fs_emu_warning("Could not find texture %s\n", full_name); return NULL; } } fs_image *image = fs_image_new_from_file(path); fs_emu_log("loading texture \"%s\"\n", path); free(path); if (image == NULL) { fs_emu_warning("Could not load texture from %s\n", full_name); free(full_name); return NULL; } free(full_name); if (fs_emu_get_video_format() == FS_EMU_VIDEO_FORMAT_BGRA) { // convert to premultiplied alpha if (image->format == FS_IMAGE_FORMAT_RGBA) { int num_pixels = image->width * image->height; unsigned char *pixels = image->data; for (int i = 0; i < num_pixels; i++) { unsigned char alpha = pixels[3]; unsigned char temp = pixels[2]; pixels[2] = ((int) pixels[0]) * alpha / 255; pixels[1] = ((int) pixels[1]) * alpha / 255; pixels[0] = ((int) temp) * alpha / 255; pixels += 4; } } else { // FIXME: should swap R and B here... } } else { // convert to premultiplied alpha if (image->format == FS_IMAGE_FORMAT_RGBA) { int num_pixels = image->width * image->height; unsigned char *pixels = image->data; for (int i = 0; i < num_pixels; i++) { unsigned char alpha = pixels[3]; // should really divide by 255, but 256 is faster... //pixels[0] = ((int) pixels[0]) * alpha / 256; //pixels[1] = ((int) pixels[1]) * alpha / 256; //pixels[2] = ((int) pixels[2]) * alpha / 256; pixels[0] = ((int) pixels[0]) * alpha / 255; pixels[1] = ((int) pixels[1]) * alpha / 255; pixels[2] = ((int) pixels[2]) * alpha / 255; //pixels[0] = (unsigned char) ((pixels[0] * alpha + 0.5) / 255.0); //pixels[1] = (unsigned char) ((pixels[1] * alpha + 0.5) / 255.0); //pixels[2] = (unsigned char) ((pixels[2] * alpha + 0.5) / 255.0); pixels += 4; } } } fs_emu_texture *texture = fs_new(fs_emu_texture, 1); texture->width = image->width; texture->height = image->height; texture->image = image; load_texture(texture); fs_emu_set_texture(texture); fs_gl_add_context_notification(context_notification_handler, texture); return texture; }
static void load_atlas_texture(fs_image *atlas_image, int texture_id, const char *name) { char *path = fs_emu_theme_get_resource(name); if (!path) { fs_emu_warning("Could not find resource %s\n", name); return; } fs_image *image = fs_image_new_from_file(path); if (!image) { fs_emu_warning("error loading texture \"%s\"\n", name); return; } fs_emu_log("loaded sub-texture from \"%s\"\n", path); // find needed number of cells int cw = (image->width + 7) / 8; int ch = (image->height + 7) / 8; // adding 1 to get some spacing between cells if (cw < 128) { cw++; } if (ch < 128) { ch++; } // try to find space for it in the texture atlas using a simple // brute-force search int cx = 0; int cy = 0; int ok = 0; for (cy = 0; cy <= 128 - ch; cy++) { for (cx = 0; cx <= 128 - cw; cx++) { if (check_placement(cx, cy, cw, ch)) { ok = 1; break; } } if (ok) { break; } } if (!ok) { fs_emu_warning("could not find space for \"%s\"\n", name); //printf("%d %d %d %d\n", cx * 8, cy * 8, cw * 8, ch * 8); return; } // mark cells as used for (int y = cy; y < cy + ch; y++) { for (int x = cx; x < cx + cw; x++) { g_cells[y][x] = 1; } } //printf("%d %d %d %d\n", cx * 8, cy * 8, cw * 8, ch * 8); // copy sub-texture into texture, also converting to pre-multiplied // alpha, and BGRA if needed. Also copy border pixels to pixels outside // border to fix unwanted bilinear filtering effects int dx = cx * 8; int dy = cy * 8; int ds = atlas_image->width * 4; // stride unsigned char *dst = atlas_image->data + \ (dy * atlas_image->width + dx) * 4; unsigned char *sp = image->data; for (int y = 0; y < image->height; y++) { #if 1 if (y == 0 && dy > 0) { // repeat first line unsigned char *dp = dst - ds; for (int x = 0; x < image->width; x++) { copy_pixel(&dp, &sp); } sp -= image->width * 4; } #endif unsigned char *dp = dst; for (int x = 0; x < image->width; x++) { copy_pixel(&dp, &sp); } dst += 1024 * 4; // stride #if 1 if (y == image->height - 1 && dy + y - 1 < atlas_image->height - 1) { // repeat last line sp -= image->width * 4; unsigned char *dp = dst; for (int x = 0; x < image->width; x++) { copy_pixel(&dp, &sp); } } #endif } // repeat left and right borders uint32_t *idata = (uint32_t *) atlas_image->data; int iwidth = atlas_image->width; int y1 = dy; int y2 = dy + image->height - 1; if (y1 > 0) { y1 -= 1; } if (y2 < atlas_image->height - 1) { y2 += 1; } if (dx > 0) { for (int y = y1; y <= y2; y++) { idata[y * iwidth + dx - 1] = idata[y * iwidth + dx]; } } if (dx + image->width - 1 < atlas_image->width - 1) { for (int y = y1; y <= y2; y++) { idata[y * iwidth + dx + image->width - 1 + 1] = \ idata[y * iwidth + dx + image->width - 1]; } } // register texture coordinates g_entries[texture_id].x = cx * 8; g_entries[texture_id].y = cy * 8; g_entries[texture_id].w = image->width; g_entries[texture_id].h = image->height; // and finally free the sub-texture image fs_unref(image); }