Chromium Code Reviews| 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 |