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 194 195 void 196 ServerCursor::LastReferenceReleased() 197 { 198 if (fManager == NULL || fManager->RemoveCursor(this)) 199 delete this; 200 } 201 202