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; }
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; }
static struct grub_font_glyph * grub_font_construct_dry_run (grub_font_t hinted_font, const struct grub_unicode_glyph *glyph_id, struct grub_video_signed_rect *bounds, struct grub_font_glyph **combining_glyphs, int *device_width) { struct grub_font_glyph *main_glyph = NULL; grub_uint32_t desired_attributes = 0; unsigned i; grub_uint32_t base = glyph_id->base; const struct grub_unicode_combining *comb; if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED) desired_attributes |= GRUB_FONT_CODE_RIGHT_JOINED; if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_LEFT_JOINED) desired_attributes |= GRUB_FONT_CODE_LEFT_JOINED; comb = grub_unicode_get_comb (glyph_id); if (base == 'i' || base == 'j') { for (i = 0; i < glyph_id->ncomb; i++) if (comb[i].type == GRUB_UNICODE_STACK_ABOVE) break; if (i < glyph_id->ncomb && base == 'i') base = GRUB_UNICODE_DOTLESS_LOWERCASE_I; if (i < glyph_id->ncomb && base == 'j') base = GRUB_UNICODE_DOTLESS_LOWERCASE_J; } main_glyph = grub_font_get_glyph_with_fallback (hinted_font, base | desired_attributes); if (!main_glyph) main_glyph = grub_font_get_glyph_with_fallback (hinted_font, base); /* Glyph not available in any font. Use ASCII fallback. */ if (!main_glyph) main_glyph = ascii_glyph_lookup (base); /* Glyph not available in any font. Return unknown glyph. */ if (!main_glyph) return NULL; if (device_width) *device_width = main_glyph->device_width; if (!glyph_id->ncomb && !glyph_id->attributes) return main_glyph; if (glyph_id->ncomb && !combining_glyphs) { grub_errno = GRUB_ERR_NONE; return main_glyph; } for (i = 0; i < glyph_id->ncomb; i++) combining_glyphs[i] = grub_font_get_glyph_with_fallback (main_glyph->font, comb[i].code); blit_comb (glyph_id, NULL, bounds, main_glyph, combining_glyphs, device_width); return main_glyph; }