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, 39 int32 flags, BPoint hotspot, 40 int32 bytesPerRow, 41 screen_id screen) 42 : ServerBitmap(r, format, flags, bytesPerRow, screen), 43 fHotSpot(hotspot), 44 fOwningTeam(-1), 45 fReferenceCount(1), 46 fCursorData(NULL), 47 fManager(NULL), 48 fPendingViewCursor(0) 49 { 50 fHotSpot.ConstrainTo(Bounds()); 51 _AllocateBuffer(); 52 } 53 54 55 /*! 56 \brief Constructor 57 \param data Pointer to 68-byte cursor data array. See BeBook entry for BCursor for details 58 */ 59 ServerCursor::ServerCursor(const uint8* data) 60 : ServerBitmap(BRect(0, 0, 15, 15), B_RGBA32, 0), 61 fHotSpot(0, 0), 62 fOwningTeam(-1), 63 fReferenceCount(1), 64 fCursorData(NULL), 65 fManager(NULL), 66 fPendingViewCursor(0) 67 { 68 // 68-byte array used in R5 for holding cursors. 69 // This API has serious problems and should be deprecated(but supported) in R2 70 71 // Now that we have all the setup, we're going to map (for now) the cursor 72 // to RGBA32 (little endian). Eventually, there will be support for 16 and 73 // 8-bit depths 74 // NOTE: review this once we have working PPC graphics cards (big endian). 75 if (data) { 76 _AllocateBuffer(); 77 uint8* buffer = Bits(); 78 if (!buffer) 79 return; 80 81 uint16* cursorBits = (uint16*)(data + 4); 82 uint16* transparencyBits = (uint16*)(data + 36); 83 fHotSpot.Set(data[3], data[2]); 84 85 // for each row in the cursor data 86 for (int32 j = 0; j < 16; j++) { 87 uint32* bits = (uint32*)(buffer + (j * BytesPerRow())); 88 89 // On intel, our bytes end up swapped, so we must swap them back 90 uint16 cursorLine = __swap_int16(cursorBits[j]); 91 uint16 transparencyLine = __swap_int16(transparencyBits[j]); 92 93 uint16 mask = 1 << 15; 94 95 // for each column in each row of cursor data 96 for (int32 i = 0; i < 16; i++, mask >>= 1) { 97 // Get the values and dump them to the bitmap 98 if (cursorLine & mask) 99 bits[i] = 0xff000000; // black 100 else if (transparencyLine & mask) 101 bits[i] = 0xffffffff; // white 102 else 103 bits[i] = 0x00000000; // transparent 104 } 105 } 106 107 // remember cursor data for later 108 fCursorData = new (nothrow) uint8[68]; 109 if (fCursorData) 110 memcpy(fCursorData, data, 68); 111 112 } else { 113 fWidth = 0; 114 fHeight = 0; 115 fBytesPerRow = 0; 116 fSpace = B_NO_COLOR_SPACE; 117 } 118 } 119 120 121 /*! 122 \brief Constructor 123 \param data Pointer to bitmap data in memory, 124 the padding bytes should be contained when format less than 32 bpp. 125 */ 126 ServerCursor::ServerCursor(const uint8* alreadyPaddedData, 127 uint32 width, uint32 height, 128 color_space format) 129 : ServerBitmap(BRect(0, 0, width - 1, height - 1), format, 0), 130 fHotSpot(0, 0), 131 fOwningTeam(-1), 132 fReferenceCount(1), 133 fCursorData(NULL), 134 fManager(NULL), 135 fPendingViewCursor(0) 136 { 137 _AllocateBuffer(); 138 if (Bits()) 139 memcpy(Bits(), alreadyPaddedData, BitsLength()); 140 } 141 142 143 /*! 144 \brief Copy constructor 145 \param cursor cursor to copy 146 */ 147 ServerCursor::ServerCursor(const ServerCursor* cursor) 148 : ServerBitmap(cursor), 149 fHotSpot(0, 0), 150 fOwningTeam(-1), 151 fReferenceCount(1), 152 fCursorData(NULL), 153 fManager(NULL), 154 fPendingViewCursor(0) 155 { 156 // TODO: Hm. I don't move this into the if clause, 157 // because it might break code elsewhere. 158 _AllocateBuffer(); 159 160 if (cursor) { 161 if (Bits() && cursor->Bits()) 162 memcpy(Bits(), cursor->Bits(), BitsLength()); 163 fHotSpot = cursor->fHotSpot; 164 if (cursor->fCursorData) { 165 fCursorData = new (nothrow) uint8[68]; 166 if (fCursorData) 167 memcpy(fCursorData, cursor->fCursorData, 68); 168 } 169 } 170 } 171 172 173 //! Frees the heap space allocated for the cursor's image data 174 ServerCursor::~ServerCursor() 175 { 176 } 177 178 179 /*! 180 \brief Sets the cursor's hotspot 181 \param pt New location of hotspot, constrained to the cursor's boundaries. 182 */ 183 void 184 ServerCursor::SetHotSpot(BPoint hotSpot) 185 { 186 fHotSpot = hotSpot; 187 fHotSpot.ConstrainTo(Bounds()); 188 } 189 190 191 bool 192 ServerCursor::Release() 193 { 194 if (atomic_add(&fReferenceCount, -1) == 1) { 195 if (fPendingViewCursor > 0) { 196 // There is a SetViewCursor() waiting to be carried out 197 return false; 198 } 199 200 if (fManager && !fManager->RemoveCursor(this)) 201 return false; 202 203 delete this; 204 return true; 205 } 206 return false; 207 } 208 209 210 void 211 ServerCursor::SetPendingViewCursor(bool pending) 212 { 213 atomic_add(&fPendingViewCursor, pending ? 1 : -1); 214 } 215 216 217 void 218 ServerCursor::AttachedToManager(CursorManager* manager) 219 { 220 fManager = manager; 221 } 222 223