xref: /haiku/src/servers/app/ServerCursor.cpp (revision eea5774f46bba925156498abf9cb1a1165647bf7)
1 /*
2  * Copyright 2001-2009, Haiku.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		DarkWyrm <bpmagic@columbus.rr.com>
7  *		Stephan Aßmus <superstippi@gmx.de>
8  *		Axel Dörfler, axeld@pinc-software.de
9  */
10 
11 
12 /*!	Although descended from ServerBitmaps, ServerCursors are not handled by
13 	the BitmapManager, but the CursorManager instead. Until they have been
14 	attached to a CursorManager, you can delete cursors like any other object.
15 
16 	Unlike BeOS, cursors can be any size or color space, and this class
17 	accomodates and expands the BeOS API.
18 */
19 
20 
21 #include "CursorManager.h"
22 #include "ServerCursor.h"
23 
24 #include <ByteOrder.h>
25 
26 #include <new>
27 #include <stdio.h>
28 
29 
30 using std::nothrow;
31 
32 
33 /*!	\brief Constructor
34 
35 	\param r Size of the cursor
36 	\param cspace Color space of the cursor
37 	\param flags ServerBitmap flags. See Bitmap.h.
38 	\param hotspot Hotspot of the cursor
39 	\param bytesperline Bytes per row for the cursor. See
40 		ServerBitmap::ServerBitmap()
41 
42 */
43 ServerCursor::ServerCursor(BRect r, color_space format, int32 flags,
44 		BPoint hotspot, int32 bytesPerRow, screen_id screen)
45 	:
46 	ServerBitmap(r, format, flags, bytesPerRow, screen),
47 	fHotSpot(hotspot),
48 	fOwningTeam(-1),
49 	fCursorData(NULL),
50 	fManager(NULL)
51 {
52 	fHotSpot.ConstrainTo(Bounds());
53 	AllocateBuffer();
54 }
55 
56 
57 /*!	\brief Constructor
58 	\param data Pointer to 68-byte cursor data array. See BeBook entry for
59 		BCursor for details
60 */
61 ServerCursor::ServerCursor(const uint8* data)
62 	:
63 	ServerBitmap(BRect(0, 0, 15, 15), B_RGBA32, 0),
64 	fHotSpot(0, 0),
65 	fOwningTeam(-1),
66 	fCursorData(NULL),
67 	fManager(NULL)
68 {
69 	// 68-byte array used in BeOS for holding cursors.
70 	// This API has serious problems and should be deprecated (but supported)
71 	// in R2
72 
73 	// Now that we have all the setup, we're going to map (for now) the cursor
74 	// to RGBA32 (little endian). Eventually, there will be support for 16 and
75 	// 8-bit depths
76 	// NOTE: review this once we have working PPC graphics cards (big endian).
77 	if (data) {
78 		AllocateBuffer();
79 		uint8* buffer = Bits();
80 		if (!buffer)
81 			return;
82 
83 		uint16* cursorBits = (uint16*)(data + 4);
84 		uint16* transparencyBits = (uint16*)(data + 36);
85 		fHotSpot.Set(data[3], data[2]);
86 
87 		// for each row in the cursor data
88 		for (int32 j = 0; j < 16; j++) {
89 			uint32* bits = (uint32*)(buffer + (j * BytesPerRow()));
90 
91 			// On intel, our bytes end up swapped, so we must swap them back
92 			uint16 cursorLine = __swap_int16(cursorBits[j]);
93 			uint16 transparencyLine = __swap_int16(transparencyBits[j]);
94 
95 			uint16 mask = 1 << 15;
96 
97 			// for each column in each row of cursor data
98 			for (int32 i = 0; i < 16; i++, mask >>= 1) {
99 				// Get the values and dump them to the bitmap
100 				if (cursorLine & mask)
101 					bits[i] = 0xff000000; // black
102 				else if (transparencyLine & mask)
103 					bits[i] = 0xffffffff; // white
104 				else
105 					bits[i] = 0x00000000; // transparent
106 			}
107 		}
108 
109 		// remember cursor data for later
110 		fCursorData = new (nothrow) uint8[68];
111 		if (fCursorData)
112 			memcpy(fCursorData, data, 68);
113 
114 	} else {
115 		fWidth = 0;
116 		fHeight = 0;
117 		fBytesPerRow = 0;
118 		fSpace = B_NO_COLOR_SPACE;
119 	}
120 }
121 
122 
123 /*!	\brief Constructor
124 	\param data Pointer to bitmap data in memory,
125 	the padding bytes should be contained when format less than 32 bpp.
126 */
127 ServerCursor::ServerCursor(const uint8* alreadyPaddedData, uint32 width,
128 		uint32 height, color_space format)
129 	:
130 	ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0),
131 	fHotSpot(0, 0),
132 	fOwningTeam(-1),
133 	fCursorData(NULL),
134 	fManager(NULL)
135 {
136 	AllocateBuffer();
137 	if (Bits())
138 		memcpy(Bits(), alreadyPaddedData, BitsLength());
139 }
140 
141 
142 /*!	\brief Copy constructor
143 	\param cursor cursor to copy
144 */
145 ServerCursor::ServerCursor(const ServerCursor* cursor)
146 	:
147 	ServerBitmap(cursor),
148 	fHotSpot(0, 0),
149 	fOwningTeam(-1),
150 	fCursorData(NULL),
151 	fManager(NULL)
152 {
153 	// TODO: Hm. I don't move this into the if clause,
154 	// because it might break code elsewhere.
155 	AllocateBuffer();
156 
157 	if (cursor) {
158 		if (Bits() && cursor->Bits())
159 			memcpy(Bits(), cursor->Bits(), BitsLength());
160 		fHotSpot = cursor->fHotSpot;
161 		if (cursor->fCursorData) {
162 			fCursorData = new (nothrow) uint8[68];
163 			if (fCursorData)
164 				memcpy(fCursorData, cursor->fCursorData, 68);
165 		}
166 	}
167 }
168 
169 
170 //!	Frees the heap space allocated for the cursor's image data
171 ServerCursor::~ServerCursor()
172 {
173 	delete[] fCursorData;
174 }
175 
176 
177 /*!	\brief Sets the cursor's hotspot
178 	\param pt New location of hotspot, constrained to the cursor's boundaries.
179 */
180 void
181 ServerCursor::SetHotSpot(BPoint hotSpot)
182 {
183 	fHotSpot = hotSpot;
184 	fHotSpot.ConstrainTo(Bounds());
185 }
186 
187 
188 void
189 ServerCursor::AttachedToManager(CursorManager* manager)
190 {
191 	fManager = manager;
192 }
193