From d2d36cebce2ae1c1ded7debadaf509044554c319 Mon Sep 17 00:00:00 2001 From: Vladimir 'phcoder' Serbinenko Date: Sat, 4 May 2013 22:23:23 +0200 Subject: [PATCH 425/482] Agglomerate more mallocs to speed-up gfxterm. --- ChangeLog | 4 + grub-core/font/font.c | 91 +++++++++++------ grub-core/gfxmenu/font.c | 7 +- grub-core/gfxmenu/gui_list.c | 1 + grub-core/gfxmenu/gui_progress_bar.c | 3 + grub-core/kern/term.c | 1 - grub-core/normal/charset.c | 193 +++++++++++++++++------------------ grub-core/normal/menu_entry.c | 2 +- grub-core/normal/menu_text.c | 8 +- grub-core/normal/term.c | 18 ++-- grub-core/term/gfxterm.c | 19 ++-- grub-core/tests/video_checksum.c | 10 +- grub-core/video/fb/fbblit.c | 6 -- include/grub/emu/export.h | 2 + include/grub/unicode.h | 76 ++++++++++---- 15 files changed, 254 insertions(+), 187 deletions(-) diff --git a/ChangeLog b/ChangeLog index 963792e..57bce50 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2013-05-04 Vladimir Serbinenko + Agglomerate more mallocs to speed-up gfxterm. + +2013-05-04 Vladimir Serbinenko + Speed-up gfxterm by slightly agglomerating mallocs. 2013-05-04 Vladimir Serbinenko diff --git a/grub-core/font/font.c b/grub-core/font/font.c index 4758f6c..50b1799 100644 --- a/grub-core/font/font.c +++ b/grub-core/font/font.c @@ -1064,6 +1064,7 @@ grub_font_get_glyph_with_fallback (grub_font_t font, grub_uint32_t code) return best_glyph; } +#if 0 static struct grub_font_glyph * grub_font_dup_glyph (struct grub_font_glyph *glyph) { @@ -1075,6 +1076,7 @@ grub_font_dup_glyph (struct grub_font_glyph *glyph) + (glyph->width * glyph->height + 7) / 8); return ret; } +#endif /* FIXME: suboptimal. */ static void @@ -1202,6 +1204,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, signed above_leftx, above_lefty; signed below_rightx, below_righty; signed min_devwidth = 0; + const struct grub_unicode_combining *comb; if (glyph) glyph->device_width = main_glyph->device_width; @@ -1222,6 +1225,8 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, below_rightx = ctx.bounds.x + ctx.bounds.width; below_righty = ctx.bounds.y; + comb = grub_unicode_get_comb (glyph_id); + for (i = 0; i < glyph_id->ncomb; i++) { grub_int16_t space = 0; @@ -1232,10 +1237,10 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, continue; targetx = (ctx.bounds.width - combining_glyphs[i]->width) / 2 + ctx.bounds.x; /* CGJ is to avoid diacritics reordering. */ - if (glyph_id->combining[i].code + if (comb[i].code == GRUB_UNICODE_COMBINING_GRAPHEME_JOINER) continue; - switch (glyph_id->combining[i].type) + switch (comb[i].type) { case GRUB_UNICODE_COMB_OVERLAY: do_blit (combining_glyphs[i], @@ -1361,7 +1366,7 @@ blit_comb (const struct grub_unicode_glyph *glyph_id, break; case GRUB_UNICODE_COMB_MN: - switch (glyph_id->combining[i].code) + switch (comb[i].code) { case GRUB_UNICODE_THAANA_ABAFILI: case GRUB_UNICODE_THAANA_AABAAFILI: @@ -1410,17 +1415,14 @@ 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_out, + struct grub_font_glyph **combining_glyphs, int *device_width) { struct grub_font_glyph *main_glyph = NULL; - struct grub_font_glyph **combining_glyphs; grub_uint32_t desired_attributes = 0; unsigned i; grub_uint32_t base = glyph_id->base; - - if (combining_glyphs_out) - *combining_glyphs_out = NULL; + const struct grub_unicode_combining *comb; if (glyph_id->attributes & GRUB_UNICODE_GLYPH_ATTRIBUTE_RIGHT_JOINED) desired_attributes |= GRUB_FONT_CODE_RIGHT_JOINED; @@ -1428,11 +1430,12 @@ grub_font_construct_dry_run (grub_font_t hinted_font, 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 (glyph_id->combining[i].type == GRUB_UNICODE_STACK_ABOVE) + if (comb[i].type == GRUB_UNICODE_STACK_ABOVE) break; if (i < glyph_id->ncomb && base == 'i') base = GRUB_UNICODE_DOTLESS_LOWERCASE_I; @@ -1461,8 +1464,6 @@ grub_font_construct_dry_run (grub_font_t hinted_font, if (!glyph_id->ncomb && !glyph_id->attributes) return main_glyph; - combining_glyphs = grub_malloc (sizeof (combining_glyphs[0]) - * glyph_id->ncomb); if (glyph_id->ncomb && !combining_glyphs) { grub_errno = GRUB_ERR_NONE; @@ -1472,18 +1473,33 @@ grub_font_construct_dry_run (grub_font_t hinted_font, for (i = 0; i < glyph_id->ncomb; i++) combining_glyphs[i] = grub_font_get_glyph_with_fallback (main_glyph->font, - glyph_id->combining[i].code); + comb[i].code); blit_comb (glyph_id, NULL, bounds, main_glyph, combining_glyphs, device_width); - if (combining_glyphs_out) - *combining_glyphs_out = combining_glyphs; - else - grub_free (combining_glyphs); return main_glyph; } +static struct grub_font_glyph **render_combining_glyphs = 0; +static grub_size_t render_max_comb_glyphs = 0; + +static void +ensure_comb_space (const struct grub_unicode_glyph *glyph_id) +{ + if (glyph_id->ncomb <= render_max_comb_glyphs) + return; + + render_max_comb_glyphs = 2 * glyph_id->ncomb; + if (render_max_comb_glyphs < 8) + render_max_comb_glyphs = 8; + grub_free (render_combining_glyphs); + render_combining_glyphs = grub_malloc (render_max_comb_glyphs + * sizeof (render_combining_glyphs[0])); + if (!render_combining_glyphs) + grub_errno = 0; +} + int grub_font_get_constructed_device_width (grub_font_t hinted_font, const struct grub_unicode_glyph @@ -1491,8 +1507,11 @@ grub_font_get_constructed_device_width (grub_font_t hinted_font, { int ret; struct grub_font_glyph *main_glyph; + + ensure_comb_space (glyph_id); + main_glyph = grub_font_construct_dry_run (hinted_font, glyph_id, NULL, - NULL, &ret); + render_combining_glyphs, &ret); if (!main_glyph) return unknown_glyph->device_width; return ret; @@ -1504,26 +1523,42 @@ grub_font_construct_glyph (grub_font_t hinted_font, { struct grub_font_glyph *main_glyph; struct grub_video_signed_rect bounds; - struct grub_font_glyph *glyph; - struct grub_font_glyph **combining_glyphs; + 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, &combining_glyphs, NULL); + &bounds, render_combining_glyphs, + NULL); if (!main_glyph) - return grub_font_dup_glyph (unknown_glyph); + return unknown_glyph; - if (!combining_glyphs) - return grub_font_dup_glyph (main_glyph); + if (!render_combining_glyphs && glyph_id->ncomb) + return main_glyph; + + if (!glyph_id->ncomb && !glyph_id->attributes) + return main_glyph; - glyph = - grub_zalloc (sizeof (*glyph) + (bounds.width * bounds.height + 7) / 8); + 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 grub_font_dup_glyph (main_glyph); + 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; @@ -1542,9 +1577,7 @@ grub_font_construct_glyph (grub_font_t hinted_font, (glyph->height + glyph->offset_y) - (main_glyph->height + main_glyph->offset_y)); - blit_comb (glyph_id, glyph, NULL, main_glyph, combining_glyphs, NULL); - - grub_free (combining_glyphs); + blit_comb (glyph_id, glyph, NULL, main_glyph, render_combining_glyphs, NULL); return glyph; } diff --git a/grub-core/gfxmenu/font.c b/grub-core/gfxmenu/font.c index 9c6e2d4..64d5267 100644 --- a/grub-core/gfxmenu/font.c +++ b/grub-core/gfxmenu/font.c @@ -42,7 +42,6 @@ grub_font_draw_string (const char *str, grub_font_t font, int left_x, int baseline_y) { int x; - struct grub_font_glyph *glyph; grub_uint32_t *logical; grub_ssize_t logical_len, visual_len; struct grub_unicode_glyph *visual, *ptr; @@ -60,18 +59,18 @@ grub_font_draw_string (const char *str, grub_font_t font, for (ptr = visual, x = left_x; ptr < visual + visual_len; ptr++) { grub_err_t err; + struct grub_font_glyph *glyph; glyph = grub_font_construct_glyph (font, ptr); if (!glyph) return grub_errno; err = grub_font_draw_glyph (glyph, color, x, baseline_y); x += glyph->device_width; - grub_free (glyph); if (err) return err; } for (ptr = visual; ptr < visual + visual_len; ptr++) - grub_free (ptr->combining); + grub_unicode_destroy_glyph (ptr); grub_free (visual); return GRUB_ERR_NONE; @@ -104,7 +103,7 @@ grub_font_get_string_width (grub_font_t font, const char *str) &glyph); width += grub_font_get_constructed_device_width (font, &glyph); - grub_free (glyph.combining); + grub_unicode_destroy_glyph (&glyph); } grub_free (logical); diff --git a/grub-core/gfxmenu/gui_list.c b/grub-core/gfxmenu/gui_list.c index 1a2a16d..3d227ee 100644 --- a/grub-core/gfxmenu/gui_list.c +++ b/grub-core/gfxmenu/gui_list.c @@ -87,6 +87,7 @@ list_destroy (void *vself) self->scrollbar_thumb->destroy (self->scrollbar_thumb); if (self->scrollbar_frame) self->scrollbar_frame->destroy (self->scrollbar_frame); + grub_free (self->scrollbar_thumb_pattern); grub_free (self); } diff --git a/grub-core/gfxmenu/gui_progress_bar.c b/grub-core/gfxmenu/gui_progress_bar.c index cb70930..b29efc0 100644 --- a/grub-core/gfxmenu/gui_progress_bar.c +++ b/grub-core/gfxmenu/gui_progress_bar.c @@ -59,6 +59,9 @@ static void progress_bar_destroy (void *vself) { grub_gui_progress_bar_t self = vself; + grub_free (self->theme_dir); + grub_free (self->template); + grub_free (self->id); grub_gfxmenu_timeout_unregister ((grub_gui_component_t) self); grub_free (self); } diff --git a/grub-core/kern/term.c b/grub-core/kern/term.c index 66c5971..6eca68b 100644 --- a/grub-core/kern/term.c +++ b/grub-core/kern/term.c @@ -46,7 +46,6 @@ grub_putcode_dumb (grub_uint32_t code, .variant = 0, .attributes = 0, .ncomb = 0, - .combining = 0, .estimated_width = 1 }; diff --git a/grub-core/normal/charset.c b/grub-core/normal/charset.c index ab3101b..f4268ec 100644 --- a/grub-core/normal/charset.c +++ b/grub-core/normal/charset.c @@ -435,7 +435,6 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, out->attributes = 0; out->ncomb = 0; out->estimated_width = 1; - out->combining = NULL; return 1; } @@ -473,25 +472,42 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, || comb_type == GRUB_UNICODE_COMB_ME || comb_type == GRUB_UNICODE_COMB_MN) last_comb_pointer = out->ncomb; - n = grub_realloc (out->combining, - sizeof (n[0]) * (out->ncomb + 1)); - if (!n) + + if (out->ncomb + 1 <= (int) ARRAY_SIZE (out->combining_inline)) + n = out->combining_inline; + else if (out->ncomb > (int) ARRAY_SIZE (out->combining_inline)) { - grub_errno = GRUB_ERR_NONE; - continue; + n = grub_realloc (out->combining_ptr, + sizeof (n[0]) * (out->ncomb + 1)); + if (!n) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + out->combining_ptr = n; + } + else + { + n = grub_malloc (sizeof (n[0]) * (out->ncomb + 1)); + if (!n) + { + grub_errno = GRUB_ERR_NONE; + continue; + } + grub_memcpy (n, out->combining_inline, + sizeof (out->combining_inline)); + out->combining_ptr = n; } - out->combining = n; for (j = last_comb_pointer; j < out->ncomb; j++) - if (is_type_after (out->combining[j].type, comb_type)) + if (is_type_after (n[j].type, comb_type)) break; - grub_memmove (out->combining + j + 1, - out->combining + j, + grub_memmove (n + j + 1, + n + j, (out->ncomb - j) - * sizeof (out->combining[0])); - out->combining = n; - out->combining[j].code = *ptr; - out->combining[j].type = comb_type; + * sizeof (n[0])); + n[j].code = *ptr; + n[j].type = comb_type; out->ncomb++; continue; } @@ -503,7 +519,6 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, out->attributes = 0; out->ncomb = 0; out->estimated_width = 1; - out->combining = NULL; } return ptr - in; } @@ -511,7 +526,7 @@ grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, static grub_ssize_t bidi_line_wrap (struct grub_unicode_glyph *visual_out, struct grub_unicode_glyph *visual, - grub_size_t visual_len, unsigned *levels, + grub_size_t visual_len, grub_ssize_t (*getcharwidth) (const struct grub_unicode_glyph *visual, void *getcharwidth_arg), void *getcharwidth_arg, grub_size_t maxwidth, grub_size_t startwidth, @@ -531,7 +546,7 @@ bidi_line_wrap (struct grub_unicode_glyph *visual_out, void revert (unsigned start, unsigned end) { struct grub_unicode_glyph t; - unsigned i, tl; + unsigned i; int a, b; if (pos) { @@ -549,9 +564,6 @@ bidi_line_wrap (struct grub_unicode_glyph *visual_out, pos[visual[start + i].orig_pos].x = a + b - pos[visual[start + i].orig_pos].x; pos[visual[end - i].orig_pos].x = a + b - pos[visual[end - i].orig_pos].x; } - tl = levels[start + i]; - levels[start + i] = levels[end - i]; - levels[end - i] = tl; } } @@ -611,10 +623,10 @@ bidi_line_wrap (struct grub_unicode_glyph *visual_out, unsigned i; for (i = line_start; i < k; i++) { - if (levels[i] > max_level) - max_level = levels[i]; - if (levels[i] < min_odd_level && (levels[i] & 1)) - min_odd_level = levels[i]; + if (visual[i].bidi_level > max_level) + max_level = visual[i].bidi_level; + if (visual[i].bidi_level < min_odd_level && (visual[i].bidi_level & 1)) + min_odd_level = visual[i].bidi_level; } } @@ -627,9 +639,11 @@ bidi_line_wrap (struct grub_unicode_glyph *visual_out, unsigned i; for (i = line_start; i < k; i++) { - if (i != line_start && levels[i] >= j && levels[i-1] < j) + if (i != line_start && visual[i].bidi_level >= j + && visual[i-1].bidi_level < j) in = i; - if (levels[i] >= j && (i + 1 == k || levels[i+1] < j)) + if (visual[i].bidi_level >= j && (i + 1 == k + || visual[i+1].bidi_level < j)) revert (in, i); } } @@ -639,10 +653,10 @@ bidi_line_wrap (struct grub_unicode_glyph *visual_out, unsigned i; for (i = line_start; i < k; i++) { - if (is_mirrored (visual[i].base) && levels[i]) + if (is_mirrored (visual[i].base) && visual[i].bidi_level) visual[i].attributes |= GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR; if ((visual[i].attributes & GRUB_UNICODE_GLYPH_ATTRIBUTES_JOIN) - && levels[i]) + && visual[i].bidi_level) { int left, right; left = visual[i].attributes @@ -763,8 +777,6 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, { enum grub_bidi_type type = GRUB_BIDI_TYPE_L; enum override_status {OVERRIDE_NEUTRAL = 0, OVERRIDE_R, OVERRIDE_L}; - unsigned *levels; - enum grub_bidi_type *resolved_types; unsigned base_level; enum override_status cur_override; unsigned i; @@ -808,24 +820,9 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, cur_override = stack_override[stack_depth]; } - levels = grub_malloc (sizeof (levels[0]) * logical_len); - if (!levels) - return -1; - - resolved_types = grub_malloc (sizeof (resolved_types[0]) * logical_len); - if (!resolved_types) - { - grub_free (levels); - return -1; - } - visual = grub_malloc (sizeof (visual[0]) * logical_len); if (!visual) - { - grub_free (resolved_types); - grub_free (levels); - return -1; - } + return -1; for (i = 0; i < logical_len; i++) { @@ -930,13 +927,13 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, join_state = JOIN_DEFAULT; zwj_propagate_to_previous = 1; - levels[visual_len] = cur_level; + visual[visual_len].bidi_level = cur_level; if (cur_override != OVERRIDE_NEUTRAL) - resolved_types[visual_len] = + visual[visual_len].bidi_type = (cur_override == OVERRIDE_L) ? GRUB_BIDI_TYPE_L : GRUB_BIDI_TYPE_R; else - resolved_types[visual_len] = type; + visual[visual_len].bidi_type = type; visual_len++; } } @@ -951,16 +948,16 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, unsigned prev_level, next_level, cur_run_level; unsigned last_type, last_strong_type; for (run_end = run_start; run_end < visual_len && - levels[run_end] == levels[run_start]; run_end++); + visual[run_end].bidi_level == visual[run_start].bidi_level; run_end++); if (run_start == 0) prev_level = base_level; else - prev_level = levels[run_start - 1]; + prev_level = visual[run_start - 1].bidi_level; if (run_end == visual_len) next_level = base_level; else - next_level = levels[run_end]; - cur_run_level = levels[run_start]; + next_level = visual[run_end].bidi_level; + cur_run_level = visual[run_start].bidi_level; if (prev_level & 1) last_type = GRUB_BIDI_TYPE_R; else @@ -968,48 +965,48 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, last_strong_type = last_type; for (i = run_start; i < run_end; i++) { - switch (resolved_types[i]) + switch (visual[i].bidi_type) { case GRUB_BIDI_TYPE_NSM: - resolved_types[i] = last_type; + visual[i].bidi_type = last_type; break; case GRUB_BIDI_TYPE_EN: if (last_strong_type == GRUB_BIDI_TYPE_AL) - resolved_types[i] = GRUB_BIDI_TYPE_AN; + visual[i].bidi_type = GRUB_BIDI_TYPE_AN; break; case GRUB_BIDI_TYPE_L: case GRUB_BIDI_TYPE_R: - last_strong_type = resolved_types[i]; + last_strong_type = visual[i].bidi_type; break; case GRUB_BIDI_TYPE_ES: if (last_type == GRUB_BIDI_TYPE_EN && i + 1 < run_end - && resolved_types[i + 1] == GRUB_BIDI_TYPE_EN) - resolved_types[i] = GRUB_BIDI_TYPE_EN; + && visual[i + 1].bidi_type == GRUB_BIDI_TYPE_EN) + visual[i].bidi_type = GRUB_BIDI_TYPE_EN; else - resolved_types[i] = GRUB_BIDI_TYPE_ON; + visual[i].bidi_type = GRUB_BIDI_TYPE_ON; break; case GRUB_BIDI_TYPE_ET: { unsigned j; if (last_type == GRUB_BIDI_TYPE_EN) { - resolved_types[i] = GRUB_BIDI_TYPE_EN; + visual[i].bidi_type = GRUB_BIDI_TYPE_EN; break; } for (j = i; j < run_end - && resolved_types[j] == GRUB_BIDI_TYPE_ET; j++); - if (j != run_end && resolved_types[j] == GRUB_BIDI_TYPE_EN) + && visual[j].bidi_type == GRUB_BIDI_TYPE_ET; j++); + if (j != run_end && visual[j].bidi_type == GRUB_BIDI_TYPE_EN) { for (; i < run_end - && resolved_types[i] == GRUB_BIDI_TYPE_ET; i++) - resolved_types[i] = GRUB_BIDI_TYPE_EN; + && visual[i].bidi_type == GRUB_BIDI_TYPE_ET; i++) + visual[i].bidi_type = GRUB_BIDI_TYPE_EN; i--; break; } for (; i < run_end - && resolved_types[i] == GRUB_BIDI_TYPE_ET; i++) - resolved_types[i] = GRUB_BIDI_TYPE_ON; + && visual[i].bidi_type == GRUB_BIDI_TYPE_ET; i++) + visual[i].bidi_type = GRUB_BIDI_TYPE_ON; i--; break; } @@ -1017,33 +1014,33 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, case GRUB_BIDI_TYPE_CS: if (last_type == GRUB_BIDI_TYPE_EN && i + 1 < run_end - && resolved_types[i + 1] == GRUB_BIDI_TYPE_EN) + && visual[i + 1].bidi_type == GRUB_BIDI_TYPE_EN) { - resolved_types[i] = GRUB_BIDI_TYPE_EN; + visual[i].bidi_type = GRUB_BIDI_TYPE_EN; break; } if (last_type == GRUB_BIDI_TYPE_AN && i + 1 < run_end - && (resolved_types[i + 1] == GRUB_BIDI_TYPE_AN - || (resolved_types[i + 1] == GRUB_BIDI_TYPE_EN + && (visual[i + 1].bidi_type == GRUB_BIDI_TYPE_AN + || (visual[i + 1].bidi_type == GRUB_BIDI_TYPE_EN && last_strong_type == GRUB_BIDI_TYPE_AL))) { - resolved_types[i] = GRUB_BIDI_TYPE_EN; + visual[i].bidi_type = GRUB_BIDI_TYPE_EN; break; } - resolved_types[i] = GRUB_BIDI_TYPE_ON; + visual[i].bidi_type = GRUB_BIDI_TYPE_ON; break; case GRUB_BIDI_TYPE_AL: - last_strong_type = resolved_types[i]; - resolved_types[i] = GRUB_BIDI_TYPE_R; + last_strong_type = visual[i].bidi_type; + visual[i].bidi_type = GRUB_BIDI_TYPE_R; break; default: /* Make GCC happy. */ break; } - last_type = resolved_types[i]; - if (resolved_types[i] == GRUB_BIDI_TYPE_EN + last_type = visual[i].bidi_type; + if (visual[i].bidi_type == GRUB_BIDI_TYPE_EN && last_strong_type == GRUB_BIDI_TYPE_L) - resolved_types[i] = GRUB_BIDI_TYPE_L; + visual[i].bidi_type = GRUB_BIDI_TYPE_L; } if (prev_level & 1) last_type = GRUB_BIDI_TYPE_R; @@ -1054,13 +1051,13 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, unsigned j; unsigned next_type; for (j = i; j < run_end && - (resolved_types[j] == GRUB_BIDI_TYPE_B - || resolved_types[j] == GRUB_BIDI_TYPE_S - || resolved_types[j] == GRUB_BIDI_TYPE_WS - || resolved_types[j] == GRUB_BIDI_TYPE_ON); j++); + (visual[j].bidi_type == GRUB_BIDI_TYPE_B + || visual[j].bidi_type == GRUB_BIDI_TYPE_S + || visual[j].bidi_type == GRUB_BIDI_TYPE_WS + || visual[j].bidi_type == GRUB_BIDI_TYPE_ON); j++); if (j == i) { - if (resolved_types[i] == GRUB_BIDI_TYPE_L) + if (visual[i].bidi_type == GRUB_BIDI_TYPE_L) last_type = GRUB_BIDI_TYPE_L; else last_type = GRUB_BIDI_TYPE_R; @@ -1071,39 +1068,39 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, next_type = (next_level & 1) ? GRUB_BIDI_TYPE_R : GRUB_BIDI_TYPE_L; else { - if (resolved_types[j] == GRUB_BIDI_TYPE_L) + if (visual[j].bidi_type == GRUB_BIDI_TYPE_L) next_type = GRUB_BIDI_TYPE_L; else next_type = GRUB_BIDI_TYPE_R; } if (next_type == last_type) for (; i < j; i++) - resolved_types[i] = last_type; + visual[i].bidi_type = last_type; else for (; i < j; i++) - resolved_types[i] = (cur_run_level & 1) ? GRUB_BIDI_TYPE_R + visual[i].bidi_type = (cur_run_level & 1) ? GRUB_BIDI_TYPE_R : GRUB_BIDI_TYPE_L; } } for (i = 0; i < visual_len; i++) { - if (!(levels[i] & 1) && resolved_types[i] == GRUB_BIDI_TYPE_R) + if (!(visual[i].bidi_level & 1) && visual[i].bidi_type == GRUB_BIDI_TYPE_R) { - levels[i]++; + visual[i].bidi_level++; continue; } - if (!(levels[i] & 1) && (resolved_types[i] == GRUB_BIDI_TYPE_AN - || resolved_types[i] == GRUB_BIDI_TYPE_EN)) + if (!(visual[i].bidi_level & 1) && (visual[i].bidi_type == GRUB_BIDI_TYPE_AN + || visual[i].bidi_type == GRUB_BIDI_TYPE_EN)) { - levels[i] += 2; + visual[i].bidi_level += 2; continue; } - if ((levels[i] & 1) && (resolved_types[i] == GRUB_BIDI_TYPE_L - || resolved_types[i] == GRUB_BIDI_TYPE_AN - || resolved_types[i] == GRUB_BIDI_TYPE_EN)) + if ((visual[i].bidi_level & 1) && (visual[i].bidi_type == GRUB_BIDI_TYPE_L + || visual[i].bidi_type == GRUB_BIDI_TYPE_AN + || visual[i].bidi_type == GRUB_BIDI_TYPE_EN)) { - levels[i]++; + visual[i].bidi_level++; continue; } } @@ -1111,16 +1108,14 @@ grub_bidi_line_logical_to_visual (const grub_uint32_t *logical, else { for (i = 0; i < visual_len; i++) - levels[i] = 0; + visual[i].bidi_level = 0; } - grub_free (resolved_types); { grub_ssize_t ret; - ret = bidi_line_wrap (visual_out, visual, visual_len, levels, + ret = bidi_line_wrap (visual_out, visual, visual_len, getcharwidth, getcharwidth_arg, maxwidth, startwidth, contchar, pos, primitive_wrap, log_end); - grub_free (levels); grub_free (visual); return ret; } diff --git a/grub-core/normal/menu_entry.c b/grub-core/normal/menu_entry.c index 3cc0c01..fae258a 100644 --- a/grub-core/normal/menu_entry.c +++ b/grub-core/normal/menu_entry.c @@ -624,7 +624,7 @@ backward_char (struct screen *screen, int update) linep->buf + screen->column) - linep->buf; - grub_free (glyph.combining); + grub_unicode_destroy_glyph (&glyph); } else if (screen->line > 0) { diff --git a/grub-core/normal/menu_text.c b/grub-core/normal/menu_text.c index d7e5641..36f8e73 100644 --- a/grub-core/normal/menu_text.c +++ b/grub-core/normal/menu_text.c @@ -56,10 +56,10 @@ grub_getstringwidth (grub_uint32_t * str, const grub_uint32_t * last_position, while (str < last_position) { struct grub_unicode_glyph glyph; - glyph.combining = 0; + glyph.ncomb = 0; str += grub_unicode_aglomerate_comb (str, last_position - str, &glyph); width += grub_term_getcharwidth (term, &glyph); - grub_free (glyph.combining); + grub_unicode_destroy_glyph (&glyph); } return width; } @@ -259,7 +259,8 @@ print_entry (int y, int highlight, grub_menu_entry_t entry, len - i, &glyph); width = grub_term_getcharwidth (term, &glyph); - grub_free (glyph.combining); + + grub_unicode_destroy_glyph (&glyph); if (x + width <= (int) (GRUB_TERM_LEFT_BORDER_X + grub_term_border_width (term) @@ -284,7 +285,6 @@ print_entry (int y, int highlight, grub_menu_entry_t entry, .variant = 0, .attributes = 0, .ncomb = 0, - .combining = 0, .estimated_width = 1 }; x += grub_term_getcharwidth (term, &pseudo_glyph); diff --git a/grub-core/normal/term.c b/grub-core/normal/term.c index 820156f..83b3bce 100644 --- a/grub-core/normal/term.c +++ b/grub-core/normal/term.c @@ -29,7 +29,7 @@ struct term_state { struct term_state *next; - const struct grub_unicode_glyph *backlog_glyphs; + struct grub_unicode_glyph *backlog_glyphs; const grub_uint32_t *backlog_ucs4; int backlog_fixed_tab; grub_size_t backlog_len; @@ -228,7 +228,6 @@ grub_puts_terminal (const char *str, struct grub_term_output *term) .variant = 0, .attributes = 0, .ncomb = 0, - .combining = 0, .estimated_width = 1, .base = *str }; @@ -422,7 +421,6 @@ putglyph (const struct grub_unicode_glyph *c, struct grub_term_output *term, .variant = 0, .attributes = 0, .ncomb = 0, - .combining = 0, .estimated_width = 1 }; @@ -475,7 +473,7 @@ putglyph (const struct grub_unicode_glyph *c, struct grub_term_output *term, } } else - code = c->combining[i].code; + code = grub_unicode_get_comb (c) [i].code; grub_ucs4_to_utf8 (&code, 1, u8, sizeof (u8)); @@ -506,7 +504,6 @@ putcode_real (grub_uint32_t code, struct grub_term_output *term, int fixed_tab) .variant = 0, .attributes = 0, .ncomb = 0, - .combining = 0, .estimated_width = 1 }; @@ -534,7 +531,6 @@ get_maxwidth (struct grub_term_output *term, .variant = 0, .attributes = 0, .ncomb = 0, - .combining = 0 }; return (grub_term_width (term) - grub_term_getcharwidth (term, &space_glyph) @@ -615,7 +611,6 @@ print_ucs4_terminal (const grub_uint32_t * str, .variant = 0, .attributes = 0, .ncomb = 0, - .combining = 0 }; c.base = *ptr; if (pos) @@ -779,14 +774,14 @@ find_term_state (struct grub_term_output *term) } static int -put_glyphs_terminal (const struct grub_unicode_glyph *visual, +put_glyphs_terminal (struct grub_unicode_glyph *visual, grub_ssize_t visual_len, int margin_left, int margin_right, struct grub_term_output *term, struct term_state *state, int fixed_tab, grub_uint32_t contchar) { - const struct grub_unicode_glyph *visual_ptr; + struct grub_unicode_glyph *visual_ptr; int since_last_nl = 1; for (visual_ptr = visual; visual_ptr < visual + visual_len; visual_ptr++) { @@ -813,7 +808,7 @@ put_glyphs_terminal (const struct grub_unicode_glyph *visual, grub_term_gotoxy (term, margin_left, grub_term_getxy (term) & 0xff); } - grub_free (visual_ptr->combining); + grub_unicode_destroy_glyph (visual_ptr); } if (contchar && since_last_nl) fill_margin (term, margin_right); @@ -953,7 +948,7 @@ print_ucs4_real (const grub_uint32_t * str, if (visual_len_show && visual[visual_len_show - 1].base != '\n') ret++; for (vptr = visual; vptr < visual + visual_len; vptr++) - grub_free (vptr->combining); + grub_unicode_destroy_glyph (vptr); grub_free (visual); } else @@ -1030,7 +1025,6 @@ grub_xnputs (const char *str, grub_size_t msg_len) .variant = 0, .attributes = 0, .ncomb = 0, - .combining = 0, .estimated_width = 1, .base = *str }; diff --git a/grub-core/term/gfxterm.c b/grub-core/term/gfxterm.c index 0cb4037..0e5bcd9 100644 --- a/grub-core/term/gfxterm.c +++ b/grub-core/term/gfxterm.c @@ -175,7 +175,7 @@ set_term_color (grub_uint8_t term_color) static void clear_char (struct grub_colored_char *c) { - grub_free (c->code.combining); + grub_unicode_destroy_glyph (&c->code); grub_unicode_set_glyph_from_code (&c->code, ' '); c->fg_color = virtual_screen.fg_color; c->bg_color = virtual_screen.bg_color; @@ -191,7 +191,7 @@ grub_virtual_screen_free (void) for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++) - grub_free (virtual_screen.text_buffer[i].code.combining); + grub_unicode_destroy_glyph (&virtual_screen.text_buffer[i].code); grub_free (virtual_screen.text_buffer); } @@ -267,7 +267,7 @@ grub_virtual_screen_setup (unsigned int x, unsigned int y, /* Clear out text buffer. */ for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++) { - virtual_screen.text_buffer[i].code.combining = 0; + virtual_screen.text_buffer[i].code.ncomb = 0; clear_char (&(virtual_screen.text_buffer[i])); } @@ -408,8 +408,8 @@ grub_gfxterm_term_fini (struct grub_term_output *term __attribute__ ((unused))) for (i = 0; i < virtual_screen.columns * virtual_screen.rows; i++) { - grub_free (virtual_screen.text_buffer[i].code.combining); - virtual_screen.text_buffer[i].code.combining = 0; + grub_unicode_destroy_glyph (&virtual_screen.text_buffer[i].code); + virtual_screen.text_buffer[i].code.ncomb = 0; virtual_screen.text_buffer[i].code.base = 0; } @@ -651,7 +651,6 @@ paint_char (unsigned cx, unsigned cy) /* Mark character to be drawn. */ dirty_region_add (virtual_screen.offset_x + x, virtual_screen.offset_y + y, width, height); - grub_free (glyph); } static inline void @@ -804,8 +803,8 @@ scroll_up (void) /* Clear first line in text buffer. */ for (i = 0; i < virtual_screen.columns; i++) - grub_free (virtual_screen.text_buffer[i].code.combining); - + grub_unicode_destroy_glyph (&virtual_screen.text_buffer[i].code); + /* Scroll text buffer with one line to up. */ grub_memmove (virtual_screen.text_buffer, virtual_screen.text_buffer + virtual_screen.columns, @@ -877,7 +876,7 @@ grub_gfxterm_putchar (struct grub_term_output *term, p = (virtual_screen.text_buffer + virtual_screen.cursor_x + virtual_screen.cursor_y * virtual_screen.columns); - grub_free (p->code.combining); + grub_unicode_destroy_glyph (&p->code); grub_unicode_set_glyph (&p->code, c); grub_errno = GRUB_ERR_NONE; p->fg_color = virtual_screen.fg_color; @@ -892,7 +891,7 @@ grub_gfxterm_putchar (struct grub_term_output *term, virtual_screen.text_buffer + virtual_screen.columns * virtual_screen.rows; i++) { - grub_free (p[i].code.combining); + grub_unicode_destroy_glyph (&p[i].code); p[i].code.base = 0; } } diff --git a/grub-core/tests/video_checksum.c b/grub-core/tests/video_checksum.c index 68c61ff..ec9d33a 100644 --- a/grub-core/tests/video_checksum.c +++ b/grub-core/tests/video_checksum.c @@ -478,6 +478,11 @@ int genfd = -1; #include +#if defined (GRUB_MACHINE_EMU) && defined (COLLECT_TIME_STATISTICS) +#include +#include +#endif + static void write_time (void) { @@ -486,9 +491,12 @@ write_time (void) static grub_uint64_t prev; grub_uint64_t cur; static int tmrfd = -1; + struct tms tm; if (tmrfd < 0) tmrfd = open ("time.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); - cur = grub_get_time_ms (); + + times (&tm); + cur = (tm.tms_utime * 1000ULL) / sysconf(_SC_CLK_TCK); grub_snprintf (buf, sizeof (buf), "%s_%dx%dx%s:%d: %" PRIuGRUB_UINT64_T " ms\n", basename, capt_mode_info.width, diff --git a/grub-core/video/fb/fbblit.c b/grub-core/video/fb/fbblit.c index c206ac8..789507e 100644 --- a/grub-core/video/fb/fbblit.c +++ b/grub-core/video/fb/fbblit.c @@ -1085,15 +1085,9 @@ grub_video_fbblit_replace_index_RGBX8888 (struct grub_video_fbblit_info *dst, { color = *srcptr++; -#ifdef GRUB_CPU_WORDS_BIGENDIAN - sb = (color >> 0) & 0xFF; - sg = (color >> 8) & 0xFF; - sr = (color >> 16) & 0xFF; -#else sr = (color >> 0) & 0xFF; sg = (color >> 8) & 0xFF; sb = (color >> 16) & 0xFF; -#endif color = grub_video_fb_map_rgb(sr, sg, sb); *dstptr++ = color & 0xFF; diff --git a/include/grub/emu/export.h b/include/grub/emu/export.h index 7f9e4e1..4da9c47 100644 --- a/include/grub/emu/export.h +++ b/include/grub/emu/export.h @@ -5,3 +5,5 @@ void EXPORT_FUNC (write) (void); void EXPORT_FUNC (ioctl) (void); void EXPORT_FUNC (__errno_location) (void); void EXPORT_FUNC (strerror) (void); +void EXPORT_FUNC (sysconf) (void); +void EXPORT_FUNC (times) (void); diff --git a/include/grub/unicode.h b/include/grub/unicode.h index 3d79c4c..d38ddbf 100644 --- a/include/grub/unicode.h +++ b/include/grub/unicode.h @@ -132,21 +132,33 @@ enum grub_comb_type GRUB_UNICODE_COMB_MN = 255, }; +struct grub_unicode_combining +{ + grub_uint32_t code:21; + enum grub_comb_type type:8; +}; /* This structure describes a glyph as opposed to character. */ struct grub_unicode_glyph { - grub_uint32_t base; - grub_uint16_t variant:9; - grub_uint8_t attributes:5; - grub_size_t ncomb; - grub_size_t orig_pos; - struct grub_unicode_combining { - grub_uint32_t code; - enum grub_comb_type type; - } *combining; + grub_uint32_t base:23; /* minimum: 21 */ + grub_uint16_t variant:9; /* minimum: 9 */ + + grub_uint8_t attributes:5; /* minimum: 5 */ + grub_uint8_t bidi_level:6; /* minimum: 6 */ + enum grub_bidi_type bidi_type:5; /* minimum: :5 */ + + unsigned ncomb:8; /* Hint by unicode subsystem how wide this character usually is. Real width is determined by font. Set only in UTF-8 stream. */ - int estimated_width; + int estimated_width:8; + + grub_size_t orig_pos; + union + { + struct grub_unicode_combining combining_inline[sizeof (void *) + / sizeof (struct grub_unicode_combining)]; + struct grub_unicode_combining *combining_ptr; + }; }; #define GRUB_UNICODE_GLYPH_ATTRIBUTE_MIRROR 0x1 @@ -253,6 +265,24 @@ grub_size_t grub_unicode_aglomerate_comb (const grub_uint32_t *in, grub_size_t inlen, struct grub_unicode_glyph *out); +static inline const struct grub_unicode_combining * +grub_unicode_get_comb (const struct grub_unicode_glyph *in) +{ + if (in->ncomb == 0) + return NULL; + if (in->ncomb > ARRAY_SIZE (in->combining_inline)) + return in->combining_ptr; + return in->combining_inline; +} + +static inline void +grub_unicode_destroy_glyph (struct grub_unicode_glyph *glyph) +{ + if (glyph->ncomb > ARRAY_SIZE (glyph->combining_inline)) + grub_free (glyph->combining_ptr); + glyph->ncomb = 0; +} + static inline struct grub_unicode_glyph * grub_unicode_glyph_dup (const struct grub_unicode_glyph *in) { @@ -260,17 +290,20 @@ grub_unicode_glyph_dup (const struct grub_unicode_glyph *in) if (!out) return NULL; grub_memcpy (out, in, sizeof (*in)); - if (in->combining) + if (in->ncomb > ARRAY_SIZE (out->combining_inline)) { - out->combining = grub_malloc (in->ncomb * sizeof (out->combining[0])); - if (!out->combining) + out->combining_ptr = grub_malloc (in->ncomb * sizeof (out->combining_ptr[0])); + if (!out->combining_ptr) { grub_free (out); return NULL; } - grub_memcpy (out->combining, in->combining, - in->ncomb * sizeof (out->combining[0])); + grub_memcpy (out->combining_ptr, in->combining_ptr, + in->ncomb * sizeof (out->combining_ptr[0])); } + else + grub_memcpy (&out->combining_inline, &in->combining_inline, + sizeof (out->combining_inline)); return out; } @@ -279,14 +312,17 @@ grub_unicode_set_glyph (struct grub_unicode_glyph *out, const struct grub_unicode_glyph *in) { grub_memcpy (out, in, sizeof (*in)); - if (in->combining) + if (in->ncomb > ARRAY_SIZE (out->combining_inline)) { - out->combining = grub_malloc (in->ncomb * sizeof (out->combining[0])); - if (!out->combining) + out->combining_ptr = grub_malloc (in->ncomb * sizeof (out->combining_ptr[0])); + if (!out->combining_ptr) return; - grub_memcpy (out->combining, in->combining, - in->ncomb * sizeof (out->combining[0])); + grub_memcpy (out->combining_ptr, in->combining_ptr, + in->ncomb * sizeof (out->combining_ptr[0])); } + else + grub_memcpy (&out->combining_inline, &in->combining_inline, + sizeof (out->combining_inline)); } static inline struct grub_unicode_glyph * -- 1.8.2.1