static void image_destroy (void *vself) { grub_gui_image_t self = vself; /* Free the scaled bitmap, unless it's a reference to the raw bitmap. */ if (self->bitmap && (self->bitmap != self->raw_bitmap)) grub_video_bitmap_destroy (self->bitmap); if (self->raw_bitmap) grub_video_bitmap_destroy (self->raw_bitmap); grub_free (self); }
/* Get the icon for the specified class CLASS_NAME. If an icon for CLASS_NAME already exists in the cache, then a reference to the cached bitmap is returned. If it is not cached, then it is loaded and cached. If no icon could be could for CLASS_NAME, then 0 is returned. */ static struct grub_video_bitmap * get_icon_by_class (grub_gfxmenu_icon_manager_t mgr, const char *class_name) { /* First check the icon cache. */ icon_entry_t entry; for (entry = mgr->cache.next; entry; entry = entry->next) { if (grub_strcmp (entry->class_name, class_name) == 0) return entry->bitmap; } if (! mgr->theme_path) return 0; /* Otherwise, we search for an icon to load. */ char *theme_dir = grub_get_dirname (mgr->theme_path); char *icons_dir; struct grub_video_bitmap *icon; icon = 0; /* First try the theme's own icons, from "grub/themes/NAME/icons/" */ icons_dir = grub_resolve_relative_path (theme_dir, "icons/"); if (icons_dir) { icon = try_loading_icon (mgr, icons_dir, class_name); grub_free (icons_dir); } grub_free (theme_dir); if (! icon) { const char *icondir; icondir = grub_env_get ("icondir"); if (icondir) icon = try_loading_icon (mgr, icondir, class_name); } /* No icon was found. */ /* This should probably be noted in the cache, so that a search is not performed each time an icon for CLASS_NAME is requested. */ if (! icon) return 0; /* Insert a new cache entry for this icon. */ entry = grub_malloc (sizeof (*entry)); if (! entry) { grub_video_bitmap_destroy (icon); return 0; } entry->class_name = grub_strdup (class_name); entry->bitmap = icon; entry->next = mgr->cache.next; mgr->cache.next = entry; /* Link it into the cache. */ return entry->bitmap; }
static void destroy (grub_gfxmenu_box_t self) { unsigned i; for (i = 0; i < BOX_NUM_PIXMAPS; i++) { if (self->raw_pixmaps[i]) grub_video_bitmap_destroy(self->raw_pixmaps[i]); self->raw_pixmaps[i] = 0; if (self->scaled_pixmaps[i]) grub_video_bitmap_destroy(self->scaled_pixmaps[i]); self->scaled_pixmaps[i] = 0; } grub_free (self->raw_pixmaps); self->raw_pixmaps = 0; grub_free (self->scaled_pixmaps); self->scaled_pixmaps = 0; /* Free self: must be the last step! */ grub_free (self); }
/* Clear the icon cache. */ void grub_gfxmenu_icon_manager_clear_cache (grub_gfxmenu_icon_manager_t mgr) { icon_entry_t cur; icon_entry_t next; for (cur = mgr->cache.next; cur; cur = next) { next = cur->next; grub_free (cur->class_name); grub_video_bitmap_destroy (cur->bitmap); grub_free (cur); } mgr->cache.next = 0; }
static grub_err_t grub_cmd_tgatest (grub_command_t cmd __attribute__ ((unused)), int argc, char **args) { struct grub_video_bitmap *bitmap = 0; if (argc != 1) return grub_error (GRUB_ERR_BAD_ARGUMENT, "file name required"); grub_video_reader_tga (&bitmap, args[0]); if (grub_errno != GRUB_ERR_NONE) return grub_errno; grub_video_bitmap_destroy (bitmap); return GRUB_ERR_NONE; }
/* This function creates a new scaled version of the bitmap SRC. The new bitmap has dimensions DST_WIDTH by DST_HEIGHT. The scaling algorithm is given by SCALE_METHOD. If an error is encountered, the return code is not equal to GRUB_ERR_NONE, and the bitmap DST is either not created, or it is destroyed before this function returns. Supports only direct color modes which have components separated into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color). But because of this simplifying assumption, the implementation is greatly simplified. */ static grub_err_t grub_video_bitmap_create_scaled_internal (struct grub_video_bitmap **dst, int dst_width, int dst_height, struct grub_video_bitmap *src, int scale_method) { /* Create the new bitmap. */ grub_err_t ret; ret = grub_video_bitmap_create (dst, dst_width, dst_height, src->mode_info.blit_format); if (ret != GRUB_ERR_NONE) return ret; /* Error. */ (*dst)->transparent = src->transparent; switch (scale_method) { case GRUB_VIDEO_BITMAP_SCALE_METHOD_FASTEST: case GRUB_VIDEO_BITMAP_SCALE_METHOD_NEAREST: ret = scale_nn (*dst, src); break; case GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST: case GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR: ret = scale_bilinear (*dst, src); break; default: ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid scale method value"); break; } if (ret == GRUB_ERR_NONE) { /* Success: *dst is now a pointer to the scaled bitmap. */ return GRUB_ERR_NONE; } else { /* Destroy the bitmap and return the error code. */ grub_video_bitmap_destroy (*dst); *dst = 0; return ret; } }
/* Try to load an icon for the specified CLASS_NAME in the directory DIR. Returns 0 if the icon could not be loaded, or returns a pointer to a new bitmap if it was successful. */ static struct grub_video_bitmap * try_loading_icon (grub_gfxmenu_icon_manager_t mgr, const char *dir, const char *class_name) { char *path; int l; path = grub_malloc (grub_strlen (dir) + grub_strlen (class_name) + grub_strlen (icon_extension) + 3); if (! path) return 0; grub_strcpy (path, dir); l = grub_strlen (path); if (path[l-1] != '/') { path[l] = '/'; path[l+1] = 0; } grub_strcat (path, class_name); grub_strcat (path, icon_extension); struct grub_video_bitmap *raw_bitmap; grub_video_bitmap_load (&raw_bitmap, path); grub_free (path); grub_errno = GRUB_ERR_NONE; /* Critical to clear the error!! */ if (! raw_bitmap) return 0; struct grub_video_bitmap *scaled_bitmap; grub_video_bitmap_create_scaled (&scaled_bitmap, mgr->icon_width, mgr->icon_height, raw_bitmap, GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); grub_video_bitmap_destroy (raw_bitmap); if (! scaled_bitmap) return 0; return scaled_bitmap; }
static grub_err_t scale_pixmap (grub_gfxmenu_box_t self, int i, int w, int h) { struct grub_video_bitmap **scaled = &self->scaled_pixmaps[i]; struct grub_video_bitmap *raw = self->raw_pixmaps[i]; if (raw == 0) return grub_errno; if (w == -1) w = grub_video_bitmap_get_width (raw); if (h == -1) h = grub_video_bitmap_get_height (raw); if (*scaled == 0 || ((int) grub_video_bitmap_get_width (*scaled) != w) || ((int) grub_video_bitmap_get_height (*scaled) != h)) { if (*scaled) { grub_video_bitmap_destroy (*scaled); *scaled = 0; } /* Don't try to create a bitmap with a zero dimension. */ if (w != 0 && h != 0) grub_video_bitmap_create_scaled (scaled, w, h, raw, GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST); if (grub_errno != GRUB_ERR_NONE) { grub_error_push (); grub_error (grub_errno, "failed to scale bitmap for styled box pixmap #%d", i); } } return grub_errno; }
/* This function creates a new scaled version of the bitmap SRC. The new bitmap has dimensions DST_WIDTH by DST_HEIGHT. The scaling algorithm is given by SCALE_METHOD. If an error is encountered, the return code is not equal to GRUB_ERR_NONE, and the bitmap DST is either not created, or it is destroyed before this function returns. Supports only direct color modes which have components separated into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color). But because of this simplifying assumption, the implementation is greatly simplified. */ grub_err_t grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst, int dst_width, int dst_height, struct grub_video_bitmap *src, enum grub_video_bitmap_scale_method scale_method) { *dst = 0; grub_err_t err = verify_source_bitmap(src); if (err != GRUB_ERR_NONE) return err; if (dst_width <= 0 || dst_height <= 0) return grub_error (GRUB_ERR_BUG, "requested to scale to a size w/ a zero dimension"); /* Create the new bitmap. */ grub_err_t ret; ret = grub_video_bitmap_create (dst, dst_width, dst_height, src->mode_info.blit_format); if (ret != GRUB_ERR_NONE) return ret; /* Error. */ ret = grub_video_bitmap_scale (*dst, src, scale_method); if (ret == GRUB_ERR_NONE) { /* Success: *dst is now a pointer to the scaled bitmap. */ return GRUB_ERR_NONE; } else { /* Destroy the bitmap and return the error code. */ grub_video_bitmap_destroy (*dst); *dst = 0; return ret; } }
/* Set the specified property NAME on the view to the given string VALUE. The caller is responsible for the lifetimes of NAME and VALUE. */ static grub_err_t theme_set_string (grub_gfxmenu_view_t view, const char *name, const char *value, const char *theme_dir, const char *filename, int line_num, int col_num) { if (! grub_strcmp ("title-font", name)) view->title_font = grub_font_get (value); else if (! grub_strcmp ("message-font", name)) view->message_font = grub_font_get (value); else if (! grub_strcmp ("terminal-font", name)) { grub_free (view->terminal_font_name); view->terminal_font_name = grub_strdup (value); if (! view->terminal_font_name) return grub_errno; } else if (! grub_strcmp ("title-color", name)) grub_video_parse_color (value, &view->title_color); else if (! grub_strcmp ("message-color", name)) grub_video_parse_color (value, &view->message_color); else if (! grub_strcmp ("message-bg-color", name)) grub_video_parse_color (value, &view->message_bg_color); else if (! grub_strcmp ("desktop-image", name)) { struct grub_video_bitmap *raw_bitmap; char *path; path = grub_resolve_relative_path (theme_dir, value); if (! path) return grub_errno; if (grub_video_bitmap_load (&raw_bitmap, path) != GRUB_ERR_NONE) { grub_free (path); return grub_errno; } grub_free(path); grub_video_bitmap_destroy (view->raw_desktop_image); view->raw_desktop_image = raw_bitmap; } else if (! grub_strcmp ("desktop-image-scale-method", name)) { if (! value || ! grub_strcmp ("stretch", value)) view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_STRETCH; else if (! grub_strcmp ("crop", value)) view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP; else if (! grub_strcmp ("padding", value)) view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING; else if (! grub_strcmp ("fitwidth", value)) view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH; else if (! grub_strcmp ("fitheight", value)) view->desktop_image_scale_method = GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT; else return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported scale method: %s", value); } else if (! grub_strcmp ("desktop-image-h-align", name)) { if (! grub_strcmp ("left", value)) view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_LEFT; else if (! grub_strcmp ("center", value)) view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_CENTER; else if (! grub_strcmp ("right", value)) view->desktop_image_h_align = GRUB_VIDEO_BITMAP_H_ALIGN_RIGHT; else return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported horizontal align method: %s", value); } else if (! grub_strcmp ("desktop-image-v-align", name)) { if (! grub_strcmp ("top", value)) view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_TOP; else if (! grub_strcmp ("center", value)) view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_CENTER; else if (! grub_strcmp ("bottom", value)) view->desktop_image_v_align = GRUB_VIDEO_BITMAP_V_ALIGN_BOTTOM; else return grub_error (GRUB_ERR_BAD_ARGUMENT, "Unsupported vertical align method: %s", value); } else if (! grub_strcmp ("desktop-color", name)) grub_video_parse_color (value, &view->desktop_color); else if (! grub_strcmp ("terminal-box", name)) { grub_err_t err; err = grub_gui_recreate_box (&view->terminal_box, value, theme_dir); if (err != GRUB_ERR_NONE) return err; } else if (! grub_strcmp ("terminal-border", name)) { view->terminal_border = grub_strtoul (value, 0, 10); if (grub_errno) return grub_errno; } else if (! grub_strcmp ("terminal-left", name)) { unsigned int tmp; int err = theme_get_unsigned_int_from_proportional (value, view->screen.width, &tmp); if (err != GRUB_ERR_NONE) return err; view->terminal_rect.x = tmp; } else if (! grub_strcmp ("terminal-top", name)) { unsigned int tmp; int err = theme_get_unsigned_int_from_proportional (value, view->screen.height, &tmp); if (err != GRUB_ERR_NONE) return err; view->terminal_rect.y = tmp; } else if (! grub_strcmp ("terminal-width", name)) { unsigned int tmp; int err = theme_get_unsigned_int_from_proportional (value, view->screen.width, &tmp); if (err != GRUB_ERR_NONE) return err; view->terminal_rect.width = tmp; } else if (! grub_strcmp ("terminal-height", name)) { unsigned int tmp; int err = theme_get_unsigned_int_from_proportional (value, view->screen.height, &tmp); if (err != GRUB_ERR_NONE) return err; view->terminal_rect.height = tmp; } else if (! grub_strcmp ("title-text", name)) { grub_free (view->title_text); view->title_text = grub_strdup (value); if (! view->title_text) return grub_errno; } else { return grub_error (GRUB_ERR_BAD_ARGUMENT, "%s:%d:%d unknown property `%s'", filename, line_num, col_num, name); } return grub_errno; }
grub_err_t grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst, int dst_width, int dst_height, struct grub_video_bitmap *src, int scale, grub_video_color_t color) { int type, method; int src_width, src_height, width, height; struct grub_video_fbblit_info dst_info; struct grub_video_bitmap *tmp = 0; grub_err_t ret; *dst = 0; /* Verify the simplifying assumptions. */ if (src == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "null src bitmap in grub_video_bitmap_create_scaled"); if (src->mode_info.red_field_pos % 8 != 0 || src->mode_info.green_field_pos % 8 != 0 || src->mode_info.blue_field_pos % 8 != 0 || src->mode_info.reserved_field_pos % 8 != 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "src format not supported for scale"); if (src->mode_info.width == 0 || src->mode_info.height == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "source bitmap has a zero dimension"); if (dst_width <= 0 || dst_height <= 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "requested to scale to a size w/ a zero dimension"); if (src->mode_info.bytes_per_pixel * 8 != src->mode_info.bpp) return grub_error (GRUB_ERR_BAD_ARGUMENT, "bitmap to scale has inconsistent Bpp and bpp"); type = scale & GRUB_VIDEO_BITMAP_SCALE_TYPE_MASK; method = scale & GRUB_VIDEO_BITMAP_SCALE_METHOD_MASK; src_width = src->mode_info.width; src_height = src->mode_info.height; if ((src_width == dst_width) && (src_height == dst_height)) type = GRUB_VIDEO_BITMAP_SCALE_TYPE_CENTER; if ((type == GRUB_VIDEO_BITMAP_SCALE_TYPE_NORMAL) || (((type == GRUB_VIDEO_BITMAP_SCALE_TYPE_MINFIT) || (type == GRUB_VIDEO_BITMAP_SCALE_TYPE_MAXFIT)) && (src_width * dst_height == src_height * dst_width))) return grub_video_bitmap_create_scaled_internal (dst, dst_width, dst_height, src, method); ret = grub_video_bitmap_create (dst, dst_width, dst_height, src->mode_info.blit_format); if (ret != GRUB_ERR_NONE) return ret; /* Error. */ (*dst)->transparent = src->transparent; dst_info.mode_info = &(*dst)->mode_info; dst_info.data = (*dst)->data; color = map_color (dst_info.mode_info, color); switch (type) { case GRUB_VIDEO_BITMAP_SCALE_TYPE_MINFIT: case GRUB_VIDEO_BITMAP_SCALE_TYPE_MAXFIT: { if ((src_width * dst_height > src_height * dst_width) == (type == GRUB_VIDEO_BITMAP_SCALE_TYPE_MAXFIT)) { width = src_width * dst_height / src_height; height = dst_height; } else { width = dst_width; height = src_height * dst_width / src_width; } ret = grub_video_bitmap_create_scaled_internal (&tmp, width, height, src, method); if (ret) return ret; src = tmp; src_width = width; src_height = height; } case GRUB_VIDEO_BITMAP_SCALE_TYPE_CENTER: { int src_x, src_y, dst_x, dst_y; struct grub_video_fbblit_info src_info; width = (src_width > dst_width) ? dst_width : src_width; height = (src_height > dst_height) ? dst_height : src_height; src_x = (src_width - width) >> 1; src_y = (src_height - height) >> 1; dst_x = (dst_width - width) >> 1; dst_y = (dst_height - height) >> 1; if (dst_y) { grub_video_fbfill (&dst_info, color, 0, 0, dst_width, dst_y); grub_video_fbfill (&dst_info, color, 0, dst_y + height, dst_width, dst_height - dst_y - height); } if (dst_x) { grub_video_fbfill (&dst_info, color, 0, dst_y, dst_x, height); grub_video_fbfill (&dst_info, color, dst_x + width, dst_y, dst_width - dst_x - width, height); } src_info.mode_info = &src->mode_info; src_info.data = src->data; grub_video_fbblit (&dst_info, &src_info, GRUB_VIDEO_BLIT_REPLACE, dst_x, dst_y, width, height, src_x, src_y); break; } case GRUB_VIDEO_BITMAP_SCALE_TYPE_TILING: { int x, y; struct grub_video_fbblit_info src_info; src_info.mode_info = &src->mode_info; src_info.data = src->data; for (y = 0; y < dst_height; y += src_height) { for (x = 0; x < dst_width; x += src_width) { int w, h; w = src_width; if (x + w > dst_width) w = dst_width - x; h = src_height; if (y + h > dst_height) h = dst_height - y; grub_video_fbblit (&dst_info, &src_info, GRUB_VIDEO_BLIT_REPLACE, x, y, w, h, 0, 0); } } break; } default: return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid scale type value"); } if (tmp) grub_video_bitmap_destroy (tmp); return 0; }
/* This function creates a new scaled version of the bitmap SRC. The new bitmap has dimensions DST_WIDTH by DST_HEIGHT. The scaling algorithm is given by SCALE_METHOD. If an error is encountered, the return code is not equal to GRUB_ERR_NONE, and the bitmap DST is either not created, or it is destroyed before this function returns. Supports only direct color modes which have components separated into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color). But because of this simplifying assumption, the implementation is greatly simplified. */ grub_err_t grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst, int dst_width, int dst_height, struct grub_video_bitmap *src, enum grub_video_bitmap_scale_method scale_method) { *dst = 0; /* Verify the simplifying assumptions. */ if (src == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "null src bitmap in grub_video_bitmap_create_scaled"); if (src->mode_info.red_field_pos % 8 != 0 || src->mode_info.green_field_pos % 8 != 0 || src->mode_info.blue_field_pos % 8 != 0 || src->mode_info.reserved_field_pos % 8 != 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "src format not supported for scale"); if (src->mode_info.width == 0 || src->mode_info.height == 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "source bitmap has a zero dimension"); if (dst_width <= 0 || dst_height <= 0) return grub_error (GRUB_ERR_BAD_ARGUMENT, "requested to scale to a size w/ a zero dimension"); if (src->mode_info.bytes_per_pixel * 8 != src->mode_info.bpp) return grub_error (GRUB_ERR_BAD_ARGUMENT, "bitmap to scale has inconsistent Bpp and bpp"); /* Create the new bitmap. */ grub_err_t ret; ret = grub_video_bitmap_create (dst, dst_width, dst_height, src->mode_info.blit_format); if (ret != GRUB_ERR_NONE) return ret; /* Error. */ switch (scale_method) { case GRUB_VIDEO_BITMAP_SCALE_METHOD_FASTEST: case GRUB_VIDEO_BITMAP_SCALE_METHOD_NEAREST: ret = scale_nn (*dst, src); break; case GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST: case GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR: ret = scale_bilinear (*dst, src); break; default: ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid scale_method value"); break; } if (ret == GRUB_ERR_NONE) { /* Success: *dst is now a pointer to the scaled bitmap. */ return GRUB_ERR_NONE; } else { /* Destroy the bitmap and return the error code. */ grub_video_bitmap_destroy (*dst); *dst = 0; return ret; } }
grub_err_t grub_video_bitmap_scale_proportional (struct grub_video_bitmap **dst, int dst_width, int dst_height, struct grub_video_bitmap *src, enum grub_video_bitmap_scale_method scale_method, grub_video_bitmap_selection_method_t selection_method, grub_video_bitmap_v_align_t v_align, grub_video_bitmap_h_align_t h_align) { *dst = 0; grub_err_t ret = verify_source_bitmap(src); if (ret != GRUB_ERR_NONE) return ret; if (dst_width <= 0 || dst_height <= 0) return grub_error (GRUB_ERR_BUG, "requested to scale to a size w/ a zero dimension"); ret = grub_video_bitmap_create (dst, dst_width, dst_height, src->mode_info.blit_format); if (ret != GRUB_ERR_NONE) return ret; /* Error. */ unsigned dx0 = 0; unsigned dy0 = 0; unsigned dw = dst_width; unsigned dh = dst_height; unsigned sx0 = 0; unsigned sy0 = 0; unsigned sw = src->mode_info.width; unsigned sh = src->mode_info.height; switch (selection_method) { case GRUB_VIDEO_BITMAP_SELECTION_METHOD_CROP: /* Comparing sw/sh VS dw/dh. */ if (sw * dh < dw * sh) ret = make_v_align (&sy0, &sh, sw * dh / dw, v_align); else ret = make_h_align (&sx0, &sw, sh * dw / dh, h_align); break; case GRUB_VIDEO_BITMAP_SELECTION_METHOD_PADDING: if (sw * dh < dw * sh) ret = make_h_align (&dx0, &dw, sw * dh / sh, h_align); else ret = make_v_align (&dy0, &dh, sh * dw / sw, v_align); break; case GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITWIDTH: if (sw * dh < dw * sh) ret = make_v_align (&sy0, &sh, sw * dh / dw, v_align); else ret = make_v_align (&dy0, &dh, sh * dw / sw, v_align); break; case GRUB_VIDEO_BITMAP_SELECTION_METHOD_FITHEIGHT: if (sw * dh < dw * sh) ret = make_h_align (&dx0, &dw, sw * dh / sh, h_align); else ret = make_h_align (&sx0, &sw, sh * dw / dh, h_align); break; default: ret = grub_error (GRUB_ERR_BUG, "Invalid selection_method value"); break; } if (ret == GRUB_ERR_NONE) { /* Backup original data. */ int src_width_orig = src->mode_info.width; int src_height_orig = src->mode_info.height; grub_uint8_t *src_data_orig = src->data; int dst_width_orig = (*dst)->mode_info.width; int dst_height_orig = (*dst)->mode_info.height; grub_uint8_t *dst_data_orig = (*dst)->data; int dstride = (*dst)->mode_info.pitch; int sstride = src->mode_info.pitch; /* bytes_per_pixel is the same for both src and dst. */ int bytes_per_pixel = src->mode_info.bytes_per_pixel; /* Crop src and dst. */ src->mode_info.width = sw; src->mode_info.height = sh; src->data = (grub_uint8_t *) src->data + sx0 * bytes_per_pixel + sy0 * sstride; (*dst)->mode_info.width = dw; (*dst)->mode_info.height = dh; (*dst)->data = (grub_uint8_t *) (*dst)->data + dx0 * bytes_per_pixel + dy0 * dstride; /* Scale our image. */ ret = grub_video_bitmap_scale (*dst, src, scale_method); /* Restore original data. */ src->mode_info.width = src_width_orig; src->mode_info.height = src_height_orig; src->data = src_data_orig; (*dst)->mode_info.width = dst_width_orig; (*dst)->mode_info.height = dst_height_orig; (*dst)->data = dst_data_orig; } if (ret == GRUB_ERR_NONE) { /* Success: *dst is now a pointer to the scaled bitmap. */ return GRUB_ERR_NONE; } else { /* Destroy the bitmap and return the error code. */ grub_video_bitmap_destroy (*dst); *dst = 0; return ret; } }
static grub_err_t grub_video_reader_tga (struct grub_video_bitmap **bitmap, const char *filename) { grub_file_t file; grub_ssize_t pos; struct grub_tga_header header; int has_alpha; file = grub_buffile_open (filename, 0); if (! file) return grub_errno; /* TGA Specification states that we SHOULD start by reading ID from end of file, but we really don't care about that as we are not going to support developer area & extensions at this point. */ /* Read TGA header from beginning of file. */ if (grub_file_read (file, &header, sizeof (header)) != sizeof (header)) { grub_file_close (file); return grub_errno; } /* Skip ID field. */ pos = grub_file_tell (file); pos += header.id_length; grub_file_seek (file, pos); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (file); return grub_errno; } #if defined(TGA_DEBUG) grub_printf("tga: header\n"); dump_int_field(header.id_length); dump_int_field(header.color_map_type); dump_int_field(header.image_type); dump_int_field(header.color_map_first_index); dump_int_field(header.color_map_length); dump_int_field(header.color_map_bpp); dump_int_field(header.image_x_origin); dump_int_field(header.image_y_origin); dump_int_field(header.image_width); dump_int_field(header.image_height); dump_int_field(header.image_bpp); dump_int_field(header.image_descriptor); #endif /* Check that bitmap encoding is supported. */ switch (header.image_type) { case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: break; default: grub_file_close (file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (unknown encoding)"); } /* Check that bitmap depth is supported. */ switch (header.image_bpp) { case 24: has_alpha = 0; break; case 32: has_alpha = 1; break; default: grub_file_close (file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (bpp=%d)", header.image_bpp); } /* Allocate bitmap. If there is alpha information store it too. */ if (has_alpha) { grub_video_bitmap_create (bitmap, header.image_width, header.image_height, GRUB_VIDEO_BLIT_FORMAT_RGBA_8888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (file); return grub_errno; } /* Load bitmap data. */ switch (header.image_type) { case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: tga_load_truecolor_R8G8B8A8 (*bitmap, &header, file); break; case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: tga_load_truecolor_rle_R8G8B8A8 (*bitmap, &header, file); break; } } else { grub_video_bitmap_create (bitmap, header.image_width, header.image_height, GRUB_VIDEO_BLIT_FORMAT_RGB_888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (file); return grub_errno; } /* Load bitmap data. */ switch (header.image_type) { case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: tga_load_truecolor_R8G8B8 (*bitmap, &header, file); break; case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: tga_load_truecolor_rle_R8G8B8 (*bitmap, &header, file); break; } } /* If there was a loading problem, destroy bitmap. */ if (grub_errno != GRUB_ERR_NONE) { grub_video_bitmap_destroy (*bitmap); *bitmap = 0; } grub_file_close (file); return grub_errno; }
static grub_err_t grub_video_reader_tga (struct grub_video_bitmap **bitmap, const char *filename) { grub_ssize_t pos; struct tga_data data; grub_memset (&data, 0, sizeof (data)); data.file = grub_buffile_open (filename, 0); if (! data.file) return grub_errno; /* TGA Specification states that we SHOULD start by reading ID from end of file, but we really don't care about that as we are not going to support developer area & extensions at this point. */ /* Read TGA header from beginning of file. */ if (grub_file_read (data.file, &data.hdr, sizeof (data.hdr)) != sizeof (data.hdr)) { grub_file_close (data.file); return grub_errno; } /* Skip ID field. */ pos = grub_file_tell (data.file); pos += data.hdr.id_length; grub_file_seek (data.file, pos); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } grub_dprintf("tga", "tga: header\n"); dump_int_field(data.hdr.id_length); dump_int_field(data.hdr.color_map_type); dump_int_field(data.hdr.image_type); dump_int_field(data.hdr.color_map_first_index); dump_int_field(data.hdr.color_map_length); dump_int_field(data.hdr.color_map_bpp); dump_int_field(data.hdr.image_x_origin); dump_int_field(data.hdr.image_y_origin); dump_int_field(data.hdr.image_width); dump_int_field(data.hdr.image_height); dump_int_field(data.hdr.image_bpp); dump_int_field(data.hdr.image_descriptor); data.image_width = grub_le_to_cpu16 (data.hdr.image_width); data.image_height = grub_le_to_cpu16 (data.hdr.image_height); /* Check that bitmap encoding is supported. */ switch (data.hdr.image_type) { case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: case GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE: case GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR: data.uses_rle = 1; break; case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR: data.uses_rle = 0; break; default: grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (unknown encoding %d)", data.hdr.image_type); } data.bpp = data.hdr.image_bpp / 8; /* Check that bitmap depth is supported. */ switch (data.hdr.image_type) { case GRUB_TGA_IMAGE_TYPE_RLE_BLACK_AND_WHITE: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_BLACK_AND_WHITE: if (data.hdr.image_bpp != 8) { grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (bpp=%d)", data.hdr.image_bpp); } grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGB_888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_grayscale (&data); break; case GRUB_TGA_IMAGE_TYPE_RLE_INDEXCOLOR: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_INDEXCOLOR: if (data.hdr.image_bpp != 8 || data.hdr.color_map_bpp != 24 || data.hdr.color_map_first_index != 0) { grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (bpp=%d)", data.hdr.image_bpp); } grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGB_888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_palette (&data); tga_load_index_color (&data); break; case GRUB_TGA_IMAGE_TYPE_RLE_TRUECOLOR: case GRUB_TGA_IMAGE_TYPE_UNCOMPRESSED_TRUECOLOR: switch (data.hdr.image_bpp) { case 24: grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGB_888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_truecolor_R8G8B8 (&data); break; case 32: grub_video_bitmap_create (bitmap, data.image_width, data.image_height, GRUB_VIDEO_BLIT_FORMAT_RGBA_8888); if (grub_errno != GRUB_ERR_NONE) { grub_file_close (data.file); return grub_errno; } data.bitmap = *bitmap; /* Load bitmap data. */ tga_load_truecolor_R8G8B8A8 (&data); break; default: grub_file_close (data.file); return grub_error (GRUB_ERR_BAD_FILE_TYPE, "unsupported bitmap format (bpp=%d)", data.hdr.image_bpp); } } /* If there was a loading problem, destroy bitmap. */ if (grub_errno != GRUB_ERR_NONE) { grub_video_bitmap_destroy (*bitmap); *bitmap = 0; } grub_file_close (data.file); return grub_errno; }