| 758 | } |
| 759 | |
| 760 | bool Font::RenderImpl(Bitmap& dest, int const x, int const y, const Bitmap& sys, int color, const GlyphRet& gret) const { |
| 761 | if (EP_UNLIKELY(gret.bitmap == nullptr)) { |
| 762 | return false; |
| 763 | } |
| 764 | |
| 765 | auto rect = Rect(x, y, gret.bitmap->width(), gret.bitmap->height()); |
| 766 | if (EP_UNLIKELY(rect.width == 0)) { |
| 767 | return false; |
| 768 | } |
| 769 | |
| 770 | // Drawing position of the glyph |
| 771 | rect.x += gret.offset.x; |
| 772 | rect.y -= gret.offset.y; |
| 773 | |
| 774 | unsigned src_x = 0; |
| 775 | unsigned src_y = 0; |
| 776 | |
| 777 | int glyph_height = gret.bitmap->height() - gret.offset.y; |
| 778 | |
| 779 | // Adjust how the mask is applied depending on the glyph size to prevent that |
| 780 | // pixels from outside of the mask color are read |
| 781 | // When <= 12: Will work fine |
| 782 | // When <= 16: Slightly adjusted (see ~20 lines below) |
| 783 | if (glyph_height > 16) { |
| 784 | // Too large for the existing mask: Resize the masks (slow) |
| 785 | // The mask is too small and the system graphic must be resized |
| 786 | // This is usually an exception and requires a custom font |
| 787 | const Rect shadow_color_rect = { 16, 32, 16, 16 }; |
| 788 | const Rect mask_color_rect = { color % 10 * 16, color / 10 * 16 + 48, 16, 16 }; |
| 789 | auto sys_large = Bitmap::Create(current_style.size * 2, current_style.size, false); |
| 790 | double zoom = current_style.size / 16.0; |
| 791 | // Left half of the image is the shadow, right half the mask |
| 792 | if (color != ColorShadow && current_style.draw_shadow) { |
| 793 | sys_large->ZoomOpacityBlit(0, 0, 0, 0, sys, shadow_color_rect, zoom, zoom, Opacity::Opaque()); |
| 794 | } |
| 795 | if (!gret.has_color) { |
| 796 | sys_large->ZoomOpacityBlit(current_style.size, 0, 0, 0, sys, mask_color_rect, zoom, zoom, Opacity::Opaque()); |
| 797 | } |
| 798 | |
| 799 | if (color != ColorShadow) { |
| 800 | // First draw the shadow, offset by one |
| 801 | if (!gret.has_color && current_style.draw_shadow) { |
| 802 | auto shadow_rect = Rect(rect.x + 1, rect.y + 1, rect.width, rect.height); |
| 803 | dest.MaskedBlit(shadow_rect, *gret.bitmap, 0, 0, *sys_large, 0, 0); |
| 804 | } |
| 805 | |
| 806 | src_x = current_style.size; |
| 807 | src_y -= gret.offset.y; |
| 808 | } |
| 809 | |
| 810 | if (!gret.has_color) { |
| 811 | if (current_style.draw_gradient) { |
| 812 | dest.MaskedBlit(rect, *gret.bitmap, 0, 0, *sys_large, src_x, src_y); |
| 813 | } else { |
| 814 | auto col = sys.GetColorAt(current_style.color_offset.x + src_x, current_style.color_offset.y + src_y); |
| 815 | auto col_bm = Bitmap::Create(gret.bitmap->width(), gret.bitmap->height(), col); |
| 816 | dest.MaskedBlit(rect, *gret.bitmap, 0, 0, *col_bm, 0, 0); |
| 817 | } |
nothing calls this directly
no test coverage detected