struct grub_font_glyph * grub_font_construct_glyph (grub_font_t hinted_font, const struct grub_unicode_glyph *glyph_id) { struct grub_font_glyph *main_glyph; struct grub_video_signed_rect bounds; struct grub_font_glyph *glyph; struct grub_font_glyph **combining_glyphs; main_glyph = grub_font_construct_dry_run (hinted_font, glyph_id, &bounds, &combining_glyphs, NULL); if (!main_glyph) return grub_font_dup_glyph (unknown_glyph); if (!combining_glyphs) return grub_font_dup_glyph (main_glyph); glyph = grub_zalloc (sizeof (*glyph) + (bounds.width * bounds.height + 7) / 8); if (!glyph) { grub_errno = GRUB_ERR_NONE; return grub_font_dup_glyph (main_glyph); } glyph->font = main_glyph->font; glyph->width = bounds.width; glyph->height = bounds.height; glyph->offset_x = bounds.x; glyph->offset_y = bounds.y; if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR) grub_font_blit_glyph_mirror (glyph, main_glyph, main_glyph->offset_x - glyph->offset_x, (glyph->height + glyph->offset_y) - (main_glyph->height + main_glyph->offset_y)); else grub_font_blit_glyph (glyph, main_glyph, main_glyph->offset_x - glyph->offset_x, (glyph->height + glyph->offset_y) - (main_glyph->height + main_glyph->offset_y)); blit_comb (glyph_id, glyph, NULL, main_glyph, combining_glyphs, NULL); return glyph; }
/* Helper for blit_comb. */ static void do_blit (struct grub_font_glyph *src, signed dx, signed dy, struct blit_comb_ctx *ctx) { if (ctx->glyph) grub_font_blit_glyph (ctx->glyph, src, dx - ctx->glyph->offset_x, (ctx->glyph->height + ctx->glyph->offset_y) + dy); if (dx < ctx->bounds.x) { ctx->bounds.width += ctx->bounds.x - dx; ctx->bounds.x = dx; } if (ctx->bounds.y > -src->height - dy) { ctx->bounds.height += ctx->bounds.y - (-src->height - dy); ctx->bounds.y = (-src->height - dy); } if (dx + src->width - ctx->bounds.x >= (signed) ctx->bounds.width) ctx->bounds.width = dx + src->width - ctx->bounds.x + 1; if ((signed) ctx->bounds.height < src->height + (-src->height - dy) - ctx->bounds.y) ctx->bounds.height = src->height + (-src->height - dy) - ctx->bounds.y; }
struct grub_font_glyph * grub_font_construct_glyph (grub_font_t hinted_font, const struct grub_unicode_glyph *glyph_id) { struct grub_font_glyph *main_glyph; struct grub_video_signed_rect bounds; static struct grub_font_glyph *glyph = 0; static grub_size_t max_glyph_size = 0; ensure_comb_space (glyph_id); main_glyph = grub_font_construct_dry_run (hinted_font, glyph_id, &bounds, render_combining_glyphs, NULL); if (!main_glyph) return unknown_glyph; if (!render_combining_glyphs && glyph_id->ncomb) return main_glyph; if (!glyph_id->ncomb && !glyph_id->attributes) return main_glyph; if (max_glyph_size < sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) { grub_free (glyph); max_glyph_size = (sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT) * 2; if (max_glyph_size < 8) max_glyph_size = 8; glyph = grub_malloc (max_glyph_size); } if (!glyph) { grub_errno = GRUB_ERR_NONE; return main_glyph; } grub_memset (glyph, 0, sizeof (*glyph) + (bounds.width * bounds.height + GRUB_CHAR_BIT - 1) / GRUB_CHAR_BIT); glyph->font = main_glyph->font; glyph->width = bounds.width; glyph->height = bounds.height; glyph->offset_x = bounds.x; glyph->offset_y = bounds.y; if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR) grub_font_blit_glyph_mirror (glyph, main_glyph, main_glyph->offset_x - glyph->offset_x, (glyph->height + glyph->offset_y) - (main_glyph->height + main_glyph->offset_y)); else grub_font_blit_glyph (glyph, main_glyph, main_glyph->offset_x - glyph->offset_x, (glyph->height + glyph->offset_y) - (main_glyph->height + main_glyph->offset_y)); blit_comb (glyph_id, glyph, NULL, main_glyph, render_combining_glyphs, NULL); return glyph; }