| 704 | } |
| 705 | |
| 706 | void Bitmap::WaverBlit(int x, int y, double zoom_x, double zoom_y, Bitmap const& src, Rect const& src_rect, int depth, double phase, Opacity const& opacity, Bitmap::BlendMode blend_mode) { |
| 707 | if (opacity.IsTransparent()) { |
| 708 | return; |
| 709 | } |
| 710 | |
| 711 | Transform xform = Transform::Scale(1.0 / zoom_x, 1.0 / zoom_y); |
| 712 | |
| 713 | pixman_image_set_transform(src.bitmap.get(), &xform.matrix); |
| 714 | |
| 715 | auto mask = CreateMask(opacity, src_rect, &xform); |
| 716 | |
| 717 | int height = static_cast<int>(std::floor(src_rect.height * zoom_y)); |
| 718 | int width = static_cast<int>(std::floor(src_rect.width * zoom_x)); |
| 719 | const auto xoff = src_rect.x * zoom_x; |
| 720 | const auto yoff = src_rect.y * zoom_y; |
| 721 | const auto yclip = y < 0 ? -y : 0; |
| 722 | const auto yend = std::min(height, this->height() - y); |
| 723 | for (int i = yclip; i < yend; i++) { |
| 724 | int dy = y + i; |
| 725 | // RPG_RT starts the effect from the top of the screen even if the image is clipped. The result |
| 726 | // is that moving images which cross the top of the screen can appear to go too fast or too slow |
| 727 | // in RPT_RT. The (i - yclip) is RPG_RT compatible behavior. Just (i) would be more correct. |
| 728 | const double sy = (i - yclip) * (2 * M_PI) / (32.0 * zoom_y); |
| 729 | const int offset = 2 * zoom_x * depth * std::sin(phase + sy); |
| 730 | |
| 731 | pixman_image_composite32(src.GetOperator(mask.get(), blend_mode), |
| 732 | src.bitmap.get(), mask.get(), bitmap.get(), |
| 733 | xoff, yoff + i, |
| 734 | 0, i, |
| 735 | x + offset, dy, |
| 736 | width, 1); |
| 737 | } |
| 738 | |
| 739 | pixman_image_set_transform(src.bitmap.get(), nullptr); |
| 740 | } |
| 741 | |
| 742 | static pixman_color_t PixmanColor(const Color &color) { |
| 743 | pixman_color_t pcolor; |
no test coverage detected