1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "remoting/client/empty_cursor_filter.h"
6 
7 #include <stdint.h>
8 
9 #include <algorithm>
10 
11 #include "build/build_config.h"
12 #include "remoting/proto/control.pb.h"
13 
14 namespace remoting {
15 
EmptyCursorShape()16 protocol::CursorShapeInfo EmptyCursorShape() {
17   protocol::CursorShapeInfo empty_shape;
18   empty_shape.set_data(std::string());
19   empty_shape.set_width(0);
20   empty_shape.set_height(0);
21   empty_shape.set_hotspot_x(0);
22   empty_shape.set_hotspot_y(0);
23   return empty_shape;
24 }
25 
IsCursorShapeEmpty(const protocol::CursorShapeInfo & cursor_shape)26 bool IsCursorShapeEmpty(const protocol::CursorShapeInfo& cursor_shape) {
27   return cursor_shape.width() <= 0 || cursor_shape.height() <= 0;
28 }
29 
EmptyCursorFilter(protocol::CursorShapeStub * cursor_stub)30 EmptyCursorFilter::EmptyCursorFilter(protocol::CursorShapeStub* cursor_stub)
31     : cursor_stub_(cursor_stub) {
32 }
33 
34 EmptyCursorFilter::~EmptyCursorFilter() = default;
35 
36 namespace {
37 
38 #if defined(ARCH_CPU_LITTLE_ENDIAN)
39 const uint32_t kPixelAlphaMask = 0xff000000;
40 #else  // !defined(ARCH_CPU_LITTLE_ENDIAN)
41 const uint32_t kPixelAlphaMask = 0x000000ff;
42 #endif  // !defined(ARCH_CPU_LITTLE_ENDIAN)
43 
44 // Returns true if |pixel| is not completely transparent.
IsVisiblePixel(uint32_t pixel)45 bool IsVisiblePixel(uint32_t pixel) {
46   return (pixel & kPixelAlphaMask) != 0;
47 }
48 
49 // Returns true if there is at least one visible pixel in the given range.
IsVisibleRow(const uint32_t * begin,const uint32_t * end)50 bool IsVisibleRow(const uint32_t* begin, const uint32_t* end) {
51   return std::find_if(begin, end, &IsVisiblePixel) != end;
52 }
53 
54 }  // namespace
55 
SetCursorShape(const protocol::CursorShapeInfo & cursor_shape)56 void EmptyCursorFilter::SetCursorShape(
57     const protocol::CursorShapeInfo& cursor_shape) {
58   const uint32_t* src_row_data = reinterpret_cast<const uint32_t*>(
59       cursor_shape.data().data());
60   const uint32_t* src_row_data_end =
61       src_row_data + cursor_shape.width() * cursor_shape.height();
62   if (IsVisibleRow(src_row_data, src_row_data_end)) {
63     cursor_stub_->SetCursorShape(cursor_shape);
64     return;
65   }
66   cursor_stub_->SetCursorShape(EmptyCursorShape());
67 }
68 
69 }  // namespace remoting
70