Index: webrtc/modules/desktop_capture/screen_painter.cc |
diff --git a/webrtc/modules/desktop_capture/screen_painter.cc b/webrtc/modules/desktop_capture/screen_painter.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..52de6b756392eb4276cc59e923b9838fd0671f83 |
--- /dev/null |
+++ b/webrtc/modules/desktop_capture/screen_painter.cc |
@@ -0,0 +1,207 @@ |
+/* |
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
+ * |
+ * Use of this source code is governed by a BSD-style license |
+ * that can be found in the LICENSE file in the root of the source |
+ * tree. An additional intellectual property rights grant can be found |
+ * in the file PATENTS. All contributing project authors may |
+ * be found in the AUTHORS file in the root of the source tree. |
+ */ |
+ |
+#include "webrtc/modules/desktop_capture/screen_painter.h" |
+ |
+#include <string.h> |
+ |
+#include <algorithm> |
+#include <cstdlib> |
+#include <utility> |
+ |
+#include "webrtc/base/checks.h" |
+#include "webrtc/base/random.h" |
+#include "webrtc/base/timeutils.h" |
+ |
+namespace webrtc { |
+ |
+namespace { |
+ |
+Random* random() { |
+ static Random random(rtc::TimeMillis()); |
+ return &random; |
+} |
+ |
+} // namespace |
+ |
+// static |
+ScreenPainter::Color ScreenPainter::Color::White() { |
+ Color result; |
+ memset(&result, 0, sizeof(Color)); |
Jamie
2016/08/23 18:50:53
This will give black, not white.
Hzj_jie
2016/08/26 00:06:48
Done.
|
+ return result; |
+} |
+ |
+// static |
+ScreenPainter::Color ScreenPainter::Color::Random() { |
+ Color result; |
+ for (int i = 0; i < DesktopFrame::kBytesPerPixel - 1; i++) { |
+ result.bgra[i] = random()->Rand<uint8_t>(); |
+ } |
+ // Both Windows and Linux do not support alpha channel, so we do not bother |
+ // generating alpha value. |
+ result.bgra[DesktopFrame::kBytesPerPixel - 1] = 0; |
Jamie
2016/08/23 18:50:53
I think you want 255 here to ensure that colours a
Hzj_jie
2016/08/26 00:06:48
Done.
|
+ return result; |
+} |
+ |
+// static |
+bool ScreenPainter::Color::operator==(const uint8_t* const bgra) const { |
+ // Both Windows and Linux do not support alpha, so we do not need to check |
+ // alpha channel. |
+ for (int i = 0; i < DesktopFrame::kBytesPerPixel - 1; i++) { |
+ if (this->bgra[i] != bgra[i]) { |
+ return false; |
+ } |
+ } |
+ return true; |
+} |
+ |
+// static |
+bool ScreenPainter::Color::operator!=(const uint8_t* const bgra) const { |
+ return !(*this == bgra); |
+} |
+ |
+// static |
+bool ScreenPainter::Color::operator==(const Color right) const { |
+ return *this == right.bgra; |
+} |
+ |
+// static |
+bool ScreenPainter::Color::operator!=(const Color right) const { |
+ return !(*this == right); |
+} |
+ |
+// static |
+bool ScreenPainter::Color::PixelsMatch(const std::vector<Color>& left, |
+ const uint8_t* right) { |
+ if (left.empty()) { |
+ return true; |
+ } |
+ |
+ // On Windows 10, BitBlt returns 255 for alpha channel instead of 0. So if the |
+ // platform does not return 0 for alpha channel, use Color::operator==() |
+ // instead of memcmp. The following logic expects OS always returns zero or |
+ // non-zero for the alpha channel. If OS returns zeros for several pixels, but |
+ // non-zero for others, following logic may fail. |
Jamie
2016/08/23 18:50:53
Unless you have reason to believe that this is on
Hzj_jie
2016/08/26 00:06:48
Done.
|
+ if (right[DesktopFrame::kBytesPerPixel - 1] != 0) { |
+ for (size_t i = 0; i < left.size(); |
+ i++, right += DesktopFrame::kBytesPerPixel) { |
+ if (left[i] != right) { |
+ return false; |
+ } |
+ } |
+ return true; |
+ } |
+ |
+ return memcmp(left[0].bgra, right, left.size() * sizeof(Color)) == 0; |
+} |
+ |
+uint32_t ScreenPainter::Color::ToUInt32() const { |
+ uint32_t result = 0; |
+ for (int i = 0; i < DesktopFrame::kBytesPerPixel; i++) { |
+ result <<= 8; |
+ result += bgra[i]; |
+ } |
+ return result; |
+} |
+ |
+ScreenPainter::ScreenPainter(std::unique_ptr<ScreenDrawer> drawer) |
+ : drawer_(std::move(drawer)) { |
+ RTC_DCHECK(drawer_); |
+} |
+ |
+ScreenPainter::~ScreenPainter() {} |
+ |
+// static |
+std::unique_ptr<ScreenPainter> ScreenPainter::Create() { |
+ std::unique_ptr<ScreenDrawer> drawer = ScreenDrawer::Create(); |
+ if (drawer) { |
+ return std::unique_ptr<ScreenPainter>(new ScreenPainter(std::move(drawer))); |
+ } |
+ |
+ return nullptr; |
+} |
+ |
+DesktopRect ScreenPainter::DrawableRegion() { |
+ return drawer_->DrawableRegion(); |
+} |
+ |
+void ScreenPainter::DrawRectangle(DesktopRect rect, Color color) { |
+ rect.IntersectWith(DrawableRegion()); |
+ if (!rect.is_empty()) { |
+ drawer_->DrawRectangle(rect, color.ToUInt32()); |
+ } |
+} |
+ |
+void ScreenPainter::WaitForPendingPaintings() { |
+ drawer_->WaitForPendingPaintings(); |
+} |
+ |
+void ScreenPainter::Clear() { |
+ DrawRectangle(DrawableRegion(), Color::White()); |
+} |
+ |
+void ScreenPainter::DrawDot(DesktopVector vect, Color color) { |
+ DrawRectangle(DesktopRect::MakeXYWH(vect.x(), vect.y(), 1, 1), color); |
+} |
+ |
+ScreenPainter::Color ScreenPainter::DrawRandomColorDot(DesktopVector vect) { |
+ Color color = Color::Random(); |
+ DrawDot(vect, color); |
+ return color; |
+} |
+ |
+int ScreenPainter::DrawColorfulLine(DesktopVector start, |
+ DesktopVector end, |
+ std::vector<Color>* colors) { |
+ const int x_len = end.x() - start.x(); |
+ const int y_len = end.y() - start.y(); |
+ const int len = std::max(std::abs(x_len), std::abs(y_len)); |
+ for (int i = 0; i < len; i++) { |
+ colors->push_back(DrawRandomColorDot(DesktopVector( |
+ start.x() + i * x_len / len, start.y() + i * y_len / len))); |
+ } |
+ return len; |
+} |
+ |
+void ScreenPainter::DrawColorfulHorizontalLine(DesktopVector start, |
+ int len, |
+ std::vector<Color>* colors) { |
+ int result = DrawColorfulLine( |
+ start, DesktopVector(start.x() + len, start.y()), colors); |
+ RTC_DCHECK_EQ(result, len); |
+} |
+ |
+void ScreenPainter::DrawColorfulHorizontalLine( |
+ DesktopVector start, |
+ const std::vector<Color>& colors) { |
+ for (size_t i = 0; i < colors.size(); i++) { |
+ DrawDot(DesktopVector(start.x() + i, start.y()), colors[i]); |
+ } |
+} |
+ |
+ScreenPainter::Color ScreenPainter::DrawRandomColorRectangle(DesktopRect rect) { |
+ Color color = Color::Random(); |
+ DrawRectangle(rect, color); |
+ return color; |
+} |
+ |
+void ScreenPainter::DrawRandomColorRectangleIn(DesktopSize range, |
+ Color* color, |
+ DesktopRect* rect) { |
+ // At least a 1 x 1 updated region. |
+ const int left = random()->Rand(0, range.width() - 2); |
+ const int top = random()->Rand(0, range.height() - 2); |
+ const int right = random()->Rand(left + 1, range.width()); |
+ const int bottom = random()->Rand(top + 1, range.height()); |
+ *rect = DesktopRect::MakeLTRB(left, top, right, bottom); |
+ *color = DrawRandomColorRectangle(*rect); |
+} |
+ |
+} // namespace webrtc |