/**
 * Show an image on the screen at the given location
 */
static int show_image(ImageInfo *image, int x, int y)
{
	uint32_t inoutsize;
	void *rawimg;
	int err;

	inoutsize = image->original_size;

	if (COMPRESS_NONE == image->compression) {
		rawimg = NULL;
	} else {
		rawimg = VbExMalloc(inoutsize);
		if (VbExDecompress(image + 1, image->compressed_size,
					image->compression,
					rawimg, &inoutsize)) {
			return -1;
		}
	}

	err = VbExDisplayImage(x, y,  rawimg ? rawimg : image + 1, inoutsize);
	if (rawimg)
		VbExFree(rawimg);

	return err ? -1 : 0;
}
void VbRenderTextAtPos(const char *text, int right_to_left,
		       uint32_t x, uint32_t y, VbFont_t *font)
{
	int i;
	ImageInfo *image_info = 0;
	void *buffer;
	uint32_t buffersize;
	uint32_t cur_x = x, cur_y = y;

	if (!text || !font) {
		VBDEBUG(("  VbRenderTextAtPos: invalid args\n"));
		return;
	}

	for (i=0; text[i]; i++) {

		if (text[i] == '\n') {
			if (!image_info)
				image_info = VbFindFontGlyph(font, text[i],
							     &buffer,
							     &buffersize);
			cur_x = x;
			cur_y += image_info->height;
			continue;
		}

		image_info = VbFindFontGlyph(font, text[i], &buffer,
					     &buffersize);

		if (right_to_left)
			cur_x -= image_info->width;

		if (VBERROR_SUCCESS != VbExDisplayImage(cur_x, cur_y, buffer,
							buffersize)) {
			VBDEBUG(("  VbRenderTextAtPos: "
				 "can't display ascii 0x%x\n", text[i]));
		}

		if (!right_to_left)
			cur_x += image_info->width;
	}
}
VbError_t VbDisplayScreenFromGBB(VbCommonParams *cparams, uint32_t screen,
                                 VbNvContext *vncptr)
{
	char *fullimage = NULL;
	BmpBlockHeader hdr;
	uint32_t screen_index;
	uint32_t localization = 0;
	VbError_t retval = VBERROR_UNKNOWN;   /* Assume error until proven ok */
	uint32_t inoutsize;
	uint32_t i;
	VbFont_t *font;
	const char *text_to_show;
	int rtol = 0;
	VbError_t ret;

	ret = VbGbbReadBmpHeader(cparams, &hdr);
	if (ret)
		return ret;

	/*
	 * Translate screen ID into index.  Note that not all screens are in
	 * the GBB.
	 *
	 * TODO: ensure screen IDs match indices?  Having this translation here
	 * is awful.
	 */
	switch (screen) {
	case VB_SCREEN_DEVELOPER_WARNING:
		screen_index = SCREEN_DEVELOPER_WARNING;
		break;
	case VB_SCREEN_RECOVERY_REMOVE:
		screen_index = SCREEN_RECOVERY_REMOVE;
		break;
	case VB_SCREEN_RECOVERY_NO_GOOD:
		screen_index = SCREEN_RECOVERY_NO_GOOD;
		break;
	case VB_SCREEN_RECOVERY_INSERT:
		screen_index = SCREEN_RECOVERY_INSERT;
		break;
	case VB_SCREEN_RECOVERY_TO_DEV:
		screen_index = SCREEN_RECOVERY_TO_DEV;
		break;
	case VB_SCREEN_DEVELOPER_TO_NORM:
		screen_index = SCREEN_DEVELOPER_TO_NORM;
		break;
	case VB_SCREEN_WAIT:
		screen_index = SCREEN_WAIT;
		break;
	case VB_SCREEN_TO_NORM_CONFIRMED:
		screen_index = SCREEN_TO_NORM_CONFIRMED;
		break;
	case VB_SCREEN_BLANK:
	case VB_SCREEN_DEVELOPER_EGG:
	default:
		/* Screens which aren't in the GBB */
		VBDEBUG(("VbDisplayScreenFromGBB(): screen %d not in the GBB\n",
			 (int)screen));
		retval = VBERROR_INVALID_SCREEN_INDEX;
		goto VbDisplayScreenFromGBB_exit;
	}

	if (screen_index >= hdr.number_of_screenlayouts) {
		VBDEBUG(("VbDisplayScreenFromGBB(): "
			 "screen %d index %d not in the GBB\n",
			 (int)screen, (int)screen_index));
		retval = VBERROR_INVALID_SCREEN_INDEX;
		goto VbDisplayScreenFromGBB_exit;
	}

	/* Clip localization to number of localizations present in the GBB */
	VbNvGet(vncptr, VBNV_LOCALIZATION_INDEX, &localization);
	if (localization >= hdr.number_of_localizations) {
		localization = 0;
		VbNvSet(vncptr, VBNV_LOCALIZATION_INDEX, localization);
	}

	/* Display all bitmaps for the image */
	for (i = 0; i < MAX_IMAGE_IN_LAYOUT; i++) {
		ScreenLayout layout;
		ImageInfo image_info;
		char hwid[256];

		ret = VbGbbReadImage(cparams, localization, screen_index,
				    i, &layout, &image_info,
				    &fullimage, &inoutsize);
		if (ret == VBERROR_NO_IMAGE_PRESENT) {
			continue;
		} else if (ret) {
			retval = ret;
			goto VbDisplayScreenFromGBB_exit;
		}

		switch(image_info.format) {
		case FORMAT_BMP:
			if (i == 0) {
				/**
				 * In current version GBB bitmaps, first image
				 * is always the background.
				 */
				ret = VbExDisplaySetDimension(
						image_info.width,
						image_info.height);
				if (ret) {
					VBDEBUG(("VbExDisplaySetDimension"
						 "(%d,%d): failed (%#x).\n",
						 image_info.width,
						 image_info.height, ret));
				}
			}

			retval = VbExDisplayImage(layout.images[i].x,
						  layout.images[i].y,
						  fullimage, inoutsize);
			break;

		case FORMAT_FONT:
			/*
			 * The uncompressed blob is our font structure. Cache
			 * it as needed.
			 */
			font = VbInternalizeFontData(
					(FontArrayHeader *)fullimage);

			/* TODO: handle text in general here */
			if (TAG_HWID == image_info.tag ||
			    TAG_HWID_RTOL == image_info.tag) {
				VbRegionReadHWID(cparams, hwid, sizeof(hwid));
				text_to_show = hwid;
				rtol = (TAG_HWID_RTOL == image_info.tag);
			} else {
				text_to_show = "";
				rtol = 0;
			}

			VbRenderTextAtPos(text_to_show, rtol,
					  layout.images[i].x,
					  layout.images[i].y, font);

			VbDoneWithFontForNow(font);
			break;

		default:
			VBDEBUG(("VbDisplayScreenFromGBB(): "
				 "unsupported ImageFormat %d\n",
				 image_info.format));
			retval = VBERROR_INVALID_GBB;
		}

		VbExFree(fullimage);

		if (VBERROR_SUCCESS != retval)
			goto VbDisplayScreenFromGBB_exit;
	}

	/* Successful if all bitmaps displayed */
	retval = VBERROR_SUCCESS;

	VbRegionCheckVersion(cparams);

 VbDisplayScreenFromGBB_exit:
	VBDEBUG(("leaving VbDisplayScreenFromGBB() with %d\n",retval));
	return retval;
}