summaryrefslogtreecommitdiffstats
path: root/client/cursor.cpp
blob: 0fbf366849a4db9da21d955ff87e1fd515eccab8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
   Copyright (C) 2009 Red Hat, Inc.

   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   This library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include "common.h"
#include "cursor.h"
#include "utils.h"
#include "debug.h"

CursorData::CursorData(SpiceCursor& cursor, int data_size)
    : _atomic (1)
    , _header (cursor.header)
    , _data (NULL)
    , _opaque (NULL)
    , _local_cursor (NULL)
{
    int expected_size = 0;

    switch (cursor.header.type) {
    case SPICE_CURSOR_TYPE_ALPHA:
        expected_size = (_header.width << 2) * _header.height;
        break;
    case SPICE_CURSOR_TYPE_MONO:
        expected_size = (SPICE_ALIGN(_header.width, 8) >> 2) * _header.height;
        break;
    case SPICE_CURSOR_TYPE_COLOR4:
        expected_size = (SPICE_ALIGN(_header.width, 2) >> 1) * _header.height;
        expected_size += (SPICE_ALIGN(_header.width, 8) >> 3) * _header.height;
        expected_size += 16 * sizeof(uint32_t);
        break;
    case SPICE_CURSOR_TYPE_COLOR8:
        expected_size = _header.width * _header.height;
        expected_size += (SPICE_ALIGN(_header.width, 8) >> 3) * _header.height;
        expected_size += 256 * sizeof(uint32_t);
        break;
    case SPICE_CURSOR_TYPE_COLOR16:
        expected_size = (_header.width << 1) * _header.height;
        expected_size += (SPICE_ALIGN(_header.width, 8) >> 3) * _header.height;
        break;
    case SPICE_CURSOR_TYPE_COLOR24:
        expected_size = (_header.width * 3) * _header.height;
        expected_size += (SPICE_ALIGN(_header.width, 8) >> 3) * _header.height;
        break;
    case SPICE_CURSOR_TYPE_COLOR32:
        expected_size = (_header.width << 2) * _header.height;
        expected_size += (SPICE_ALIGN(_header.width, 8) >> 3) * _header.height;
        break;
    }

    if (data_size < expected_size) {
        THROW("access violation 0x%" PRIuPTR " %u", (uintptr_t)cursor.data, expected_size);
    }
    _data = new uint8_t[expected_size];
    memcpy(_data, cursor.data, expected_size);
}

void CursorData::set_local(LocalCursor* local_cursor)
{
    ASSERT(!_local_cursor);
    if (local_cursor) {
        _local_cursor = local_cursor->ref();
    }
}

CursorData::~CursorData()
{
    if (_local_cursor) {
        _local_cursor->unref();
    }
    delete _opaque;
    delete[] _data;
}

int LocalCursor::get_size_bits(const SpiceCursorHeader& header, int& size)
{
    switch (header.type) {
    case SPICE_CURSOR_TYPE_ALPHA:
    case SPICE_CURSOR_TYPE_COLOR32:
        size = (header.width << 2) * header.height;
        return 32;
    case SPICE_CURSOR_TYPE_MONO:
        size = (SPICE_ALIGN(header.width, 8) >> 3) * header.height;
        return 1;
    case SPICE_CURSOR_TYPE_COLOR4:
        size = (SPICE_ALIGN(header.width, 2) >> 1) * header.height;
        return 4;
    case SPICE_CURSOR_TYPE_COLOR8:
        size = header.width * header.height;
        return 8;
    case SPICE_CURSOR_TYPE_COLOR16:
        size = (header.width << 1) * header.height;
        return 16;
    case SPICE_CURSOR_TYPE_COLOR24:
        size = (header.width * 3) * header.height;
        return 24;
    default:
        return 0;
    }
}