aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Rumney2000-01-23 22:15:12 +0000
committerJason Rumney2000-01-23 22:15:12 +0000
commit00fe468b0be661e3546dfe36efd5586ef753d12d (patch)
treecec35d92cad9bdffeb5ed56275e6d91578560173 /src
parent7ed4e9a73248e14707059855470e47d1432efa7d (diff)
downloademacs-00fe468b0be661e3546dfe36efd5586ef753d12d.tar.gz
emacs-00fe468b0be661e3546dfe36efd5586ef753d12d.zip
(w32_fill_rect): Do not try to deal with NULL hdc
here. Callers changed to always pass real device context. (w32_draw_bitmap): Likewise. (w32_get_glyph_overhangs): Likewise. (w32_draw_box_rect): Make use of s->hdc rather than getting a new one. (w32_set_vertical_scroll_bar): Pass correct HWND parameters to pfnSetScrollInfo and SetScrollRange. (x_get_char_face_and_encoding): Don't turn iso8859-1 characters back into MULE characters after decoding them. (x_get_glyph_face_and_encoding): Likewise. (w32_per_char_metric): Use GetCharExtentPoint32W as fallback when GetCharABCWidthsW fails, since this is defined on Windows 9x. (x_produce_glyphs): Calculate per char metrics for a character that we know exists in default font when font_not_found_p is true.
Diffstat (limited to 'src')
-rw-r--r--src/w32term.c144
1 files changed, 82 insertions, 62 deletions
diff --git a/src/w32term.c b/src/w32term.c
index 915af573f0a..0e3df61093f 100644
--- a/src/w32term.c
+++ b/src/w32term.c
@@ -496,30 +496,18 @@ w32_draw_rectangle (HDC hdc, XGCValues *gc, int x, int y,
496 496
497/* Draw a filled rectangle at the specified position. */ 497/* Draw a filled rectangle at the specified position. */
498void 498void
499w32_fill_rect (f, _hdc, pix, lprect) 499w32_fill_rect (f, hdc, pix, lprect)
500 FRAME_PTR f; 500 FRAME_PTR f;
501 HDC _hdc; 501 HDC hdc;
502 COLORREF pix; 502 COLORREF pix;
503 RECT * lprect; 503 RECT * lprect;
504{ 504{
505 HDC hdc;
506 HBRUSH hb; 505 HBRUSH hb;
507 RECT rect; 506 RECT rect;
508 507
509 if (_hdc)
510 hdc = _hdc;
511 else
512 {
513 if (!f) return;
514 hdc = get_frame_dc (f);
515 }
516
517 hb = CreateSolidBrush (pix); 508 hb = CreateSolidBrush (pix);
518 FillRect (hdc, lprect, hb); 509 FillRect (hdc, lprect, hb);
519 DeleteObject (hb); 510 DeleteObject (hb);
520
521 if (!_hdc)
522 release_frame_dc (f, hdc);
523} 511}
524 512
525void 513void
@@ -527,9 +515,11 @@ w32_clear_window (f)
527 FRAME_PTR f; 515 FRAME_PTR f;
528{ 516{
529 RECT rect; 517 RECT rect;
518 HDC hdc = get_frame_dc (f);
530 519
531 GetClientRect (FRAME_W32_WINDOW (f), &rect); 520 GetClientRect (FRAME_W32_WINDOW (f), &rect);
532 w32_clear_rect (f, NULL, &rect); 521 w32_clear_rect (f, hdc, &rect);
522 release_frame_dc (f, hdc);
533} 523}
534 524
535 525
@@ -627,13 +617,16 @@ x_draw_vertical_border (w)
627 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f)) 617 && !FRAME_HAS_VERTICAL_SCROLL_BARS (f))
628 { 618 {
629 RECT r; 619 RECT r;
620 HDC hdc;
630 621
631 window_box_edges (w, -1, &r.left, &r.top, &r.right, &r.bottom); 622 window_box_edges (w, -1, &r.left, &r.top, &r.right, &r.bottom);
632 r.left = r.right + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f); 623 r.left = r.right + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f);
633 r.right = r.left + 1; 624 r.right = r.left + 1;
634 r.bottom -= 1; 625 r.bottom -= 1;
635 626
636 w32_fill_rect (f, NULL, FRAME_FOREGROUND_PIXEL (f), r); 627 hdc = get_frame_dc (f);
628 w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), r);
629 release_frame_dc (f, hdc);
637 } 630 }
638} 631}
639 632
@@ -727,8 +720,10 @@ x_after_update_window_line (desired_row)
727 int x = (window_box_right (w, -1) 720 int x = (window_box_right (w, -1)
728 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f)); 721 + FRAME_X_RIGHT_FLAGS_AREA_WIDTH (f));
729 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y)); 722 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
723 HDC hdc = get_frame_dc (f);
730 724
731 w32_clear_area (f, NULL, x, y, width, height); 725 w32_clear_area (f, hdc, x, y, width, height);
726 release_frame_dc (f, hdc);
732 } 727 }
733 728
734 UNBLOCK_INPUT; 729 UNBLOCK_INPUT;
@@ -742,15 +737,14 @@ x_after_update_window_line (desired_row)
742 drawn. */ 737 drawn. */
743 738
744static void 739static void
745w32_draw_bitmap (w, _hdc, row, which) 740w32_draw_bitmap (w, hdc, row, which)
746 struct window *w; 741 struct window *w;
747 HDC _hdc; 742 HDC hdc;
748 struct glyph_row *row; 743 struct glyph_row *row;
749 enum bitmap_type which; 744 enum bitmap_type which;
750{ 745{
751 struct frame *f = XFRAME (WINDOW_FRAME (w)); 746 struct frame *f = XFRAME (WINDOW_FRAME (w));
752 Window window = FRAME_W32_WINDOW (f); 747 Window window = FRAME_W32_WINDOW (f);
753 HDC hdc = _hdc ? _hdc : get_frame_dc (f);
754 HDC compat_hdc; 748 HDC compat_hdc;
755 int x, y, wd, h, dy; 749 int x, y, wd, h, dy;
756 unsigned short *bits; 750 unsigned short *bits;
@@ -848,9 +842,6 @@ w32_draw_bitmap (w, _hdc, row, which)
848 DeleteObject (fg_brush); 842 DeleteObject (fg_brush);
849 DeleteDC (compat_hdc); 843 DeleteDC (compat_hdc);
850 RestoreDC (hdc, -1); 844 RestoreDC (hdc, -1);
851
852 if (!_hdc)
853 release_frame_dc (f, hdc);
854} 845}
855 846
856 847
@@ -1102,7 +1093,7 @@ w32_per_char_metric (hdc, font, char2b, unicode_p)
1102 /* The result metric information. */ 1093 /* The result metric information. */
1103 XCharStruct *pcm; 1094 XCharStruct *pcm;
1104 ABC char_widths; 1095 ABC char_widths;
1105 int char_total_width; 1096 SIZE sz;
1106 BOOL retval; 1097 BOOL retval;
1107 1098
1108 xassert (font && char2b); 1099 xassert (font && char2b);
@@ -1125,15 +1116,17 @@ w32_per_char_metric (hdc, font, char2b, unicode_p)
1125 } 1116 }
1126 else 1117 else
1127 { 1118 {
1119 /* Windows 9x does not implement GetCharABCWidthsW, so if that
1120 failed, try GetTextExtentPoint32W, which is implemented and
1121 at least gives us some of the info we are after (total
1122 character width). */
1128 if (unicode_p) 1123 if (unicode_p)
1129 retval = GetCharWidth32W (hdc, *char2b, *char2b, &char_total_width); 1124 retval = GetTextExtentPoint32W (hdc, char2b, 1, &sz);
1130 else
1131 retval = GetCharWidth32A (hdc, *char2b, *char2b, &char_total_width);
1132 1125
1133 if (retval) 1126 if (retval)
1134 { 1127 {
1135 pcm->width = char_total_width; 1128 pcm->width = sz.cx;
1136 pcm->rbearing = char_total_width; 1129 pcm->rbearing = sz.cx;
1137 pcm->lbearing = 0; 1130 pcm->lbearing = 0;
1138 } 1131 }
1139 else 1132 else
@@ -1302,9 +1295,11 @@ x_get_char_face_and_encoding (f, c, face_id, char2b, multibyte_p)
1302 if (font_info) 1295 if (font_info)
1303 { 1296 {
1304 x_encode_char (c, char2b, font_info); 1297 x_encode_char (c, char2b, font_info);
1298#if 0 /* NTEMACS_TODO: Isn't this undoing what we just did? Investigate. */
1305 if (charset == charset_latin_iso8859_1) 1299 if (charset == charset_latin_iso8859_1)
1306 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b), 1300 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b),
1307 BYTE2 (*char2b) | 0x80); 1301 BYTE2 (*char2b) | 0x80);
1302#endif
1308 } 1303 }
1309 } 1304 }
1310 } 1305 }
@@ -1364,9 +1359,11 @@ x_get_glyph_face_and_encoding (f, glyph, char2b)
1364 if (font_info) 1359 if (font_info)
1365 { 1360 {
1366 x_encode_char (glyph->u.ch, char2b, font_info); 1361 x_encode_char (glyph->u.ch, char2b, font_info);
1362#if 0 /* NTEMACS_TODO: Isn't this undoing what we just did? Investigate. */
1367 if (charset == charset_latin_iso8859_1) 1363 if (charset == charset_latin_iso8859_1)
1368 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b), 1364 *char2b = BUILD_WCHAR_T (BYTE1 (*char2b),
1369 BYTE2 (*char2b) | 0x80); 1365 BYTE2 (*char2b) | 0x80);
1366#endif
1370 } 1367 }
1371 } 1368 }
1372 } 1369 }
@@ -1763,7 +1760,7 @@ x_produce_glyphs (it)
1763 XFontStruct *font; 1760 XFontStruct *font;
1764 struct face *face; 1761 struct face *face;
1765 XCharStruct *pcm; 1762 XCharStruct *pcm;
1766 int font_not_found_p; 1763 int font_not_found_p;
1767 struct font_info *font_info; 1764 struct font_info *font_info;
1768 int boff; /* baseline offset */ 1765 int boff; /* baseline offset */
1769 HDC hdc; 1766 HDC hdc;
@@ -1911,19 +1908,30 @@ x_produce_glyphs (it)
1911 } 1908 }
1912 else 1909 else
1913 { 1910 {
1914 /* A multi-byte character. Assume that the display width of the 1911 /* A multi-byte character.
1915 character is the width of the character multiplied by the 1912 If we found a font, this font should give us the right
1916 width of the font. */
1917
1918 /* If we found a font, this font should give us the right
1919 metrics. If we didn't find a font, use the frame's 1913 metrics. If we didn't find a font, use the frame's
1920 default font and calculate the width of the character 1914 default font and calculate the width of the character
1921 from the charset width; this is what old redisplay code 1915 from the charset width; this is what old redisplay code
1922 did. */ 1916 did. */
1923 pcm = w32_per_char_metric (hdc, font, &char2b, 1);
1924 it->pixel_width = pcm->width;
1925 if (font_not_found_p) 1917 if (font_not_found_p)
1926 it->pixel_width *= CHARSET_WIDTH (it->charset); 1918 {
1919 wchar_t dummy = BUILD_WCHAR_T (0, 'X');
1920
1921 /* Get some metrics for the default font. */
1922 pcm = w32_per_char_metric (hdc, font, &dummy, 0);
1923
1924 /* Ignore the width obtained above, and use the average
1925 width of a character in the default font. */
1926 it->pixel_width = FONT_WIDTH (font)
1927 * CHARSET_WIDTH (it->charset);
1928 }
1929 else
1930 {
1931 pcm = w32_per_char_metric (hdc, font, &char2b, 1);
1932 it->pixel_width = pcm->width;
1933 }
1934
1927 it->nglyphs = 1; 1935 it->nglyphs = 1;
1928 it->ascent = FONT_BASE (font) + boff; 1936 it->ascent = FONT_BASE (font) + boff;
1929 it->descent = FONT_DESCENT (font) - boff; 1937 it->descent = FONT_DESCENT (font) - boff;
@@ -1933,7 +1941,7 @@ x_produce_glyphs (it)
1933 && (pcm->lbearing < 0 1941 && (pcm->lbearing < 0
1934 || pcm->rbearing > pcm->width)) 1942 || pcm->rbearing > pcm->width))
1935 it->glyph_row->contains_overlapping_glyphs_p = 1; 1943 it->glyph_row->contains_overlapping_glyphs_p = 1;
1936 1944
1937 if (face->box != FACE_NO_BOX) 1945 if (face->box != FACE_NO_BOX)
1938 { 1946 {
1939 int thick = face->box_line_width; 1947 int thick = face->box_line_width;
@@ -2869,14 +2877,13 @@ x_compute_overhangs_and_x (s, x, backward_p)
2869 assumed to be zero. */ 2877 assumed to be zero. */
2870 2878
2871static void 2879static void
2872w32_get_glyph_overhangs (_hdc, glyph, f, left, right, unicode_p) 2880w32_get_glyph_overhangs (hdc, glyph, f, left, right, unicode_p)
2873 HDC _hdc; 2881 HDC hdc;
2874 struct glyph *glyph; 2882 struct glyph *glyph;
2875 struct frame *f; 2883 struct frame *f;
2876 int *left, *right, unicode_p; 2884 int *left, *right, unicode_p;
2877{ 2885{
2878 int c; 2886 int c;
2879 HDC hdc = _hdc ? _hdc : get_frame_dc (f);
2880 2887
2881 *left = *right = 0; 2888 *left = *right = 0;
2882 2889
@@ -2901,8 +2908,6 @@ w32_get_glyph_overhangs (_hdc, glyph, f, left, right, unicode_p)
2901 *left = -pcm->lbearing; 2908 *left = -pcm->lbearing;
2902 } 2909 }
2903 } 2910 }
2904 if (!_hdc)
2905 release_frame_dc (f, hdc);
2906} 2911}
2907 2912
2908 2913
@@ -3397,34 +3402,31 @@ w32_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
3397 int left_x, top_y, right_x, bottom_y, width, left_p, right_p; 3402 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
3398 RECT *clip_rect; 3403 RECT *clip_rect;
3399{ 3404{
3400 HDC hdc = get_frame_dc (s->f); 3405 w32_set_clip_rectangle (s->hdc, clip_rect);
3401
3402 w32_set_clip_rectangle (hdc, clip_rect);
3403 3406
3404 /* Top. */ 3407 /* Top. */
3405 w32_fill_area (s->f, hdc, s->face->box_color, 3408 w32_fill_area (s->f, s->hdc, s->face->box_color,
3406 left_x, top_y, right_x - left_x, width); 3409 left_x, top_y, right_x - left_x, width);
3407 3410
3408 /* Left. */ 3411 /* Left. */
3409 if (left_p) 3412 if (left_p)
3410 { 3413 {
3411 w32_fill_area (s->f, hdc, s->face->box_color, 3414 w32_fill_area (s->f, s->hdc, s->face->box_color,
3412 left_x, top_y, width, bottom_y - top_y); 3415 left_x, top_y, width, bottom_y - top_y);
3413 } 3416 }
3414 3417
3415 /* Bottom. */ 3418 /* Bottom. */
3416 w32_fill_area (s->f, hdc, s->face->box_color, 3419 w32_fill_area (s->f, s->hdc, s->face->box_color,
3417 left_x, bottom_y - width, right_x - left_x, width); 3420 left_x, bottom_y - width, right_x - left_x, width);
3418 3421
3419 /* Right. */ 3422 /* Right. */
3420 if (right_p) 3423 if (right_p)
3421 { 3424 {
3422 w32_fill_area (s->f, hdc, s->face->box_color, 3425 w32_fill_area (s->f, s->hdc, s->face->box_color,
3423 right_x - width, top_y, width, bottom_y - top_y); 3426 right_x - width, top_y, width, bottom_y - top_y);
3424 } 3427 }
3425 3428
3426 w32_set_clip_rectangle (hdc, NULL); 3429 w32_set_clip_rectangle (s->hdc, NULL);
3427 release_frame_dc (s->f, hdc);
3428} 3430}
3429 3431
3430 3432
@@ -4889,8 +4891,12 @@ x_clear_end_of_line (to_x)
4889 /* Prevent inadvertently clearing to end of the X window. */ 4891 /* Prevent inadvertently clearing to end of the X window. */
4890 if (to_x > from_x && to_y > from_y) 4892 if (to_x > from_x && to_y > from_y)
4891 { 4893 {
4894 HDC hdc;
4892 BLOCK_INPUT; 4895 BLOCK_INPUT;
4893 w32_clear_area (f, NULL, from_x, from_y, to_x - from_x, to_y - from_y); 4896 hdc = get_frame_dc (f);
4897
4898 w32_clear_area (f, hdc, from_x, from_y, to_x - from_x, to_y - from_y);
4899 release_frame_dc (f, hdc);
4894 UNBLOCK_INPUT; 4900 UNBLOCK_INPUT;
4895 } 4901 }
4896} 4902}
@@ -7167,9 +7173,13 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
7167 /* Does the scroll bar exist yet? */ 7173 /* Does the scroll bar exist yet? */
7168 if (NILP (w->vertical_scroll_bar)) 7174 if (NILP (w->vertical_scroll_bar))
7169 { 7175 {
7176 HDC hdc;
7170 BLOCK_INPUT; 7177 BLOCK_INPUT;
7171 w32_clear_area (f, NULL, left, top, width, height); 7178 hdc = get_frame_dc (f);
7179 w32_clear_area (f, hdc, left, top, width, height);
7180 release_frame_dc (f, hdc);
7172 UNBLOCK_INPUT; 7181 UNBLOCK_INPUT;
7182
7173 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height); 7183 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height);
7174 } 7184 }
7175 else 7185 else
@@ -7192,15 +7202,18 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
7192 } 7202 }
7193 else 7203 else
7194 { 7204 {
7205 HDC hdc;
7195 BLOCK_INPUT; 7206 BLOCK_INPUT;
7196 7207
7208 hdc = get_frame_dc (f);
7197 /* Since Windows scroll bars are smaller than the space reserved 7209 /* Since Windows scroll bars are smaller than the space reserved
7198 for them on the frame, we have to clear "under" them. */ 7210 for them on the frame, we have to clear "under" them. */
7199 w32_clear_area (f, NULL, 7211 w32_clear_area (f, hdc,
7200 left, 7212 left,
7201 top, 7213 top,
7202 width, 7214 width,
7203 height); 7215 height);
7216 release_frame_dc (f, hdc);
7204 7217
7205 /* Make sure scroll bar is "visible" before moving, to ensure the 7218 /* Make sure scroll bar is "visible" before moving, to ensure the
7206 area of the parent window now exposed will be refreshed. */ 7219 area of the parent window now exposed will be refreshed. */
@@ -7217,10 +7230,10 @@ w32_set_vertical_scroll_bar (w, portion, whole, position)
7217 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height) 7230 si.nMax = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height)
7218 + VERTICAL_SCROLL_BAR_MIN_HANDLE; 7231 + VERTICAL_SCROLL_BAR_MIN_HANDLE;
7219 7232
7220 pfnSetScrollInfo (w, SB_CTL, &si, FALSE); 7233 pfnSetScrollInfo (hwnd, SB_CTL, &si, FALSE);
7221 } 7234 }
7222 else 7235 else
7223 SetScrollRange (w, SB_CTL, 0, 7236 SetScrollRange (hwnd, SB_CTL, 0,
7224 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE); 7237 VERTICAL_SCROLL_BAR_TOP_RANGE (f, height), FALSE);
7225 my_show_window (f, hwnd, SW_NORMAL); 7238 my_show_window (f, hwnd, SW_NORMAL);
7226 // InvalidateRect (w, NULL, FALSE); 7239 // InvalidateRect (w, NULL, FALSE);
@@ -7681,8 +7694,11 @@ w32_read_socket (sd, bufp, numchars, expected)
7681 } 7694 }
7682 else 7695 else
7683 { 7696 {
7697 HDC hdc = get_frame_dc (f);
7698
7684 /* Erase background again for safety. */ 7699 /* Erase background again for safety. */
7685 w32_clear_rect (f, NULL, &msg.rect); 7700 w32_clear_rect (f, hdc, &msg.rect);
7701 release_frame_dc (f, hdc);
7686 expose_frame (f, 7702 expose_frame (f,
7687 msg.rect.left, 7703 msg.rect.left,
7688 msg.rect.top, 7704 msg.rect.top,
@@ -8397,7 +8413,7 @@ x_draw_bar_cursor (w, row)
8397 struct frame *f = XFRAME (w->frame); 8413 struct frame *f = XFRAME (w->frame);
8398 struct glyph *cursor_glyph; 8414 struct glyph *cursor_glyph;
8399 int x; 8415 int x;
8400 HDC hdc = get_frame_dc (f); 8416 HDC hdc;
8401 8417
8402 cursor_glyph = get_phys_cursor_glyph (w); 8418 cursor_glyph = get_phys_cursor_glyph (w);
8403 if (cursor_glyph == NULL) 8419 if (cursor_glyph == NULL)
@@ -8405,6 +8421,7 @@ x_draw_bar_cursor (w, row)
8405 8421
8406 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); 8422 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8407 8423
8424 hdc = get_frame_dc (f);
8408 w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel, 8425 w32_fill_area (f, hdc, f->output_data.w32->cursor_pixel,
8409 x, 8426 x,
8410 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y), 8427 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
@@ -8524,18 +8541,21 @@ x_erase_phys_cursor (w)
8524 { 8541 {
8525 int x; 8542 int x;
8526 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w); 8543 int header_line_height = WINDOW_DISPLAY_HEADER_LINE_HEIGHT (w);
8544 HDC hdc;
8527 8545
8528 cursor_glyph = get_phys_cursor_glyph (w); 8546 cursor_glyph = get_phys_cursor_glyph (w);
8529 if (cursor_glyph == NULL) 8547 if (cursor_glyph == NULL)
8530 goto mark_cursor_off; 8548 goto mark_cursor_off;
8531 8549
8532 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); 8550 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
8533 8551
8534 w32_clear_area (f, NULL, x, 8552 hdc = get_frame_dc (f);
8553 w32_clear_area (f, hdc, x,
8535 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height, 8554 WINDOW_TO_FRAME_PIXEL_Y (w, max (header_line_height,
8536 cursor_row->y)), 8555 cursor_row->y)),
8537 cursor_glyph->pixel_width, 8556 cursor_glyph->pixel_width,
8538 cursor_row->visible_height); 8557 cursor_row->visible_height);
8558 release_frame_dc (f, hdc);
8539 } 8559 }
8540 8560
8541 /* Erase the cursor by redrawing the character underneath it. */ 8561 /* Erase the cursor by redrawing the character underneath it. */