xref: /haiku/src/servers/app/ServerCursor.cpp (revision b671e9bbdbd10268a042b4f4cc4317ccd03d105e)
1 /*
2  * Copyright 2001-2006, 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 - they are allocated like any other object. Unlike BeOS
14 	R5, cursors can be any size or color space, and this class accomodates and
15 	expands the R5 API.
16 */
17 
18 #include "CursorManager.h"
19 #include "ServerCursor.h"
20 
21 #include <ByteOrder.h>
22 
23 #include <new>
24 #include <stdio.h>
25 
26 
27 using std::nothrow;
28 
29 /*!
30 	\brief Constructor
31 	\param r Size of the cursor
32 	\param cspace Color space of the cursor
33 	\param flags ServerBitmap flags. See Bitmap.h.
34 	\param hotspot Hotspot of the cursor
35 	\param bytesperline Bytes per row for the cursor. See ServerBitmap::ServerBitmap()
36 
37 */
38 ServerCursor::ServerCursor(BRect r, color_space format, int32 flags,
39 		BPoint hotspot, int32 bytesPerRow, screen_id screen)
40 	:
41 	ServerBitmap(r, format, flags, bytesPerRow, screen),
42 	fHotSpot(hotspot),
43 	fOwningTeam(-1),
44 	fReferenceCount(1),
45 	fCursorData(NULL),
46 	fManager(NULL)
47 {
48 	fHotSpot.ConstrainTo(Bounds());
49 	_AllocateBuffer();
50 }
51 
52 
53 /*!
54 	\brief Constructor
55 	\param data Pointer to 68-byte cursor data array. See BeBook entry for BCursor for details
56 */
57 ServerCursor::ServerCursor(const uint8* data)
58 	:
59 	ServerBitmap(BRect(0, 0, 15, 15), B_RGBA32, 0),
60 	fHotSpot(0, 0),
61 	fOwningTeam(-1),
62 	fReferenceCount(1),
63 	fCursorData(NULL),
64 	fManager(NULL)
65 {
66 	// 68-byte array used in R5 for holding cursors.
67 	// This API has serious problems and should be deprecated(but supported) in R2
68 
69 	// Now that we have all the setup, we're going to map (for now) the cursor
70 	// to RGBA32 (little endian). Eventually, there will be support for 16 and
71 	// 8-bit depths
72 	// NOTE: review this once we have working PPC graphics cards (big endian).
73 	if (data) {
74 		_AllocateBuffer();
75 		uint8* buffer = Bits();
76 		if (!buffer)
77 			return;
78 
79 		uint16* cursorBits = (uint16*)(data + 4);
80 		uint16* transparencyBits = (uint16*)(data + 36);
81 		fHotSpot.Set(data[3], data[2]);
82 
83 		// for each row in the cursor data
84 		for (int32 j = 0; j < 16; j++) {
85 			uint32* bits = (uint32*)(buffer + (j * BytesPerRow()));
86 
87 			// On intel, our bytes end up swapped, so we must swap them back
88 			uint16 cursorLine = __swap_int16(cursorBits[j]);
89 			uint16 transparencyLine = __swap_int16(transparencyBits[j]);
90 
91 			uint16 mask = 1 << 15;
92 
93 			// for each column in each row of cursor data
94 			for (int32 i = 0; i < 16; i++, mask >>= 1) {
95 				// Get the values and dump them to the bitmap
96 				if (cursorLine & mask)
97 					bits[i] = 0xff000000; // black
98 				else if (transparencyLine & mask)
99 					bits[i] = 0xffffffff; // white
100 				else
101 					bits[i] = 0x00000000; // transparent
102 			}
103 		}
104 
105 		// remember cursor data for later
106 		fCursorData = new (nothrow) uint8[68];
107 		if (fCursorData)
108 			memcpy(fCursorData, data, 68);
109 
110 	} else {
111 		fWidth = 0;
112 		fHeight = 0;
113 		fBytesPerRow = 0;
114 		fSpace = B_NO_COLOR_SPACE;
115 	}
116 }
117 
118 
119 /*!
120 	\brief Constructor
121 	\param data Pointer to bitmap data in memory,
122 	the padding bytes should be contained when format less than 32 bpp.
123 */
124 ServerCursor::ServerCursor(const uint8* alreadyPaddedData, uint32 width,
125 		uint32 height, color_space format)
126 	:
127 	ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0),
128 	fHotSpot(0, 0),
129 	fOwningTeam(-1),
130 	fReferenceCount(1),
131 	fCursorData(NULL),
132 	fManager(NULL)
133 {
134 	_AllocateBuffer();
135 	if (Bits())
136 		memcpy(Bits(), alreadyPaddedData, BitsLength());
137 }
138 
139 
140 /*!
141 	\brief Copy constructor
142 	\param cursor cursor to copy
143 */
144 ServerCursor::ServerCursor(const ServerCursor* cursor)
145 	:
146 	ServerBitmap(cursor),
147 	fHotSpot(0, 0),
148 	fOwningTeam(-1),
149 	fReferenceCount(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 /*!
178 	\brief Sets the cursor's hotspot
179 	\param pt New location of hotspot, constrained to the cursor's boundaries.
180 */
181 void
182 ServerCursor::SetHotSpot(BPoint hotSpot)
183 {
184 	fHotSpot = hotSpot;
185 	fHotSpot.ConstrainTo(Bounds());
186 }
187 
188 
189 bool
190 ServerCursor::Release()
191 {
192 	if (atomic_add(&fReferenceCount, -1) == 1) {
193 		if (fManager && !fManager->RemoveCursor(this))
194 			return false;
195 
196 		delete this;
197 		return true;
198 	}
199 	return false;
200 }
201 
202 
203 void
204 ServerCursor::AttachedToManager(CursorManager* manager)
205 {
206 	fManager = manager;
207 }
208 
209