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