| 857 | } |
| 858 | |
| 859 | void Bitmap::ToneBlit(int x, int y, Bitmap const& src, Rect const& src_rect, const Tone &tone, Opacity const& opacity) { |
| 860 | if (opacity.IsTransparent()) { |
| 861 | return; |
| 862 | } |
| 863 | |
| 864 | // Optimisations based on Opacity: |
| 865 | // Transparent: Nothing to do |
| 866 | // Opaque: Alpha check can be skipped |
| 867 | // 1 Bit: Premultiplied Alpha can be skipped |
| 868 | // 8 Bit: No optimisations possible |
| 869 | |
| 870 | auto src_opacity = src.GetImageOpacity(); |
| 871 | |
| 872 | if (src_opacity == ImageOpacity::Transparent) { |
| 873 | return; |
| 874 | } |
| 875 | |
| 876 | if (tone == Tone(128,128,128,128)) { |
| 877 | if (&src != this) { |
| 878 | Blit(x, y, src, src_rect, opacity); |
| 879 | } |
| 880 | return; |
| 881 | } |
| 882 | |
| 883 | // Only needed here, other codepaths are sanity checked by pixman |
| 884 | if (x < 0 || y < 0 || x >= width() || y >= height()) { |
| 885 | return; |
| 886 | } |
| 887 | |
| 888 | if (&src != this) { |
| 889 | pixman_image_composite32(src.GetOperator(), |
| 890 | src.bitmap.get(), nullptr, bitmap.get(), |
| 891 | src_rect.x, src_rect.y, |
| 892 | 0, 0, |
| 893 | x, y, |
| 894 | src_rect.width, src_rect.height); |
| 895 | } |
| 896 | |
| 897 | const int as = pixel_format.a.shift; |
| 898 | const int rs = pixel_format.r.shift; |
| 899 | const int gs = pixel_format.g.shift; |
| 900 | const int bs = pixel_format.b.shift; |
| 901 | int next_row = pitch() / sizeof(uint32_t); |
| 902 | uint32_t* pixels = (uint32_t*)this->pixels(); |
| 903 | pixels = pixels + (y - 1) * next_row + x; |
| 904 | |
| 905 | const uint16_t limit_height = std::min<uint16_t>(src_rect.height, height()); |
| 906 | const uint16_t limit_width = std::min<uint16_t>(src_rect.width, width()); |
| 907 | |
| 908 | const bool apply_sat = tone.gray != 128; |
| 909 | const bool apply_tone = (tone.red != 128 || tone.green != 128 || tone.blue != 128); |
| 910 | |
| 911 | // If Saturation + Color: |
| 912 | if (apply_sat && apply_tone) { |
| 913 | int sat = tone.gray > 128 ? 1024 + (tone.gray - 128) * 16 : tone.gray * 8; |
| 914 | |
| 915 | if (src_opacity == ImageOpacity::Opaque) { |
| 916 | for (uint16_t i = 0; i < limit_height; ++i) { |
no test coverage detected