1 /* 2 Open Tracker License 3 4 Terms and Conditions 5 6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved. 7 8 Permission is hereby granted, free of charge, to any person obtaining a copy of 9 this software and associated documentation files (the "Software"), to deal in 10 the Software without restriction, including without limitation the rights to 11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 12 of the Software, and to permit persons to whom the Software is furnished to do 13 so, subject to the following conditions: 14 15 The above copyright notice and this permission notice applies to all licensees 16 and shall be included in all copies or substantial portions of the Software. 17 18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY, 20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION 23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 25 Except as contained in this notice, the name of Be Incorporated shall not be 26 used in advertising or otherwise to promote the sale, use or other dealings in 27 this Software without prior written authorization from Be Incorporated. 28 29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks 30 of Be Incorporated in the United States and other countries. Other brand product 31 names are registered trademarks or trademarks of their respective holders. 32 All rights reserved. 33 */ 34 35 #include "Bitmaps.h" 36 #include "Utilities.h" 37 38 #include <Autolock.h> 39 #include <Bitmap.h> 40 #include <Debug.h> 41 #include <DataIO.h> 42 #include <File.h> 43 #include <IconUtils.h> 44 #include <String.h> 45 #include <SupportDefs.h> 46 47 48 // #pragma mark - BImageResources 49 50 51 BImageResources::BImageResources(void* memAddr) 52 { 53 image_id image = find_image(memAddr); 54 image_info info; 55 if (get_image_info(image, &info) == B_OK) { 56 #if _SUPPORTS_RESOURCES 57 BFile file(&info.name[0], B_READ_ONLY); 58 #else 59 BString name(&info.name[0]); 60 name += ".rsrc"; 61 BFile file(name.String(), B_READ_ONLY); 62 #endif 63 if (file.InitCheck() == B_OK) 64 fResources.SetTo(&file); 65 } 66 } 67 68 69 BImageResources::~BImageResources() 70 { 71 } 72 73 74 const BResources* 75 BImageResources::ViewResources() const 76 { 77 if (fLock.Lock() != B_OK) 78 return NULL; 79 80 return &fResources; 81 } 82 83 84 BResources* 85 BImageResources::ViewResources() 86 { 87 if (fLock.Lock() != B_OK) 88 return NULL; 89 90 return &fResources; 91 } 92 93 94 status_t 95 BImageResources::FinishResources(BResources* res) const 96 { 97 ASSERT(res == &fResources); 98 if (res != &fResources) 99 return B_BAD_VALUE; 100 101 fLock.Unlock(); 102 103 return B_OK; 104 } 105 106 107 const void* 108 BImageResources::LoadResource(type_code type, int32 id, 109 size_t* out_size) const 110 { 111 // Serialize execution. 112 // Looks like BResources is not really thread safe. We should 113 // clean that up in the future and remove the locking from here. 114 BAutolock lock(fLock); 115 if (!lock.IsLocked()) 116 return 0; 117 118 // Return the resource. Because we never change the BResources 119 // object, the returned data will not change until TTracker is 120 // destroyed. 121 return const_cast<BResources*>(&fResources)->LoadResource(type, id, 122 out_size); 123 } 124 125 126 const void* 127 BImageResources::LoadResource(type_code type, const char* name, 128 size_t* out_size) const 129 { 130 // Serialize execution. 131 BAutolock lock(fLock); 132 if (!lock.IsLocked()) 133 return NULL; 134 135 // Return the resource. Because we never change the BResources 136 // object, the returned data will not change until TTracker is 137 // destroyed. 138 return const_cast<BResources*>(&fResources)->LoadResource(type, name, 139 out_size); 140 } 141 142 143 status_t 144 BImageResources::GetIconResource(int32 id, icon_size size, 145 BBitmap* dest) const 146 { 147 size_t length = 0; 148 const void* data; 149 150 // try to load vector icon 151 data = LoadResource(B_VECTOR_ICON_TYPE, id, &length); 152 if (data != NULL 153 && BIconUtils::GetVectorIcon((uint8*)data, length, dest) == B_OK) { 154 return B_OK; 155 } 156 157 // fall back to R5 icon 158 length = 0; 159 size = (size == B_MINI_ICON ? B_MINI_ICON : B_LARGE_ICON); 160 161 data = LoadResource(size == B_MINI_ICON ? 'MICN' : 'ICON', id, &length); 162 if (data == NULL || length != (size_t)(size * size)) { 163 return B_ERROR; 164 } 165 166 if (dest->ColorSpace() == B_RGBA32) { 167 // fill with transparent 168 uint8* destBits = (uint8*)dest->Bits(); 169 int32 i = 0; 170 while (i < dest->BitsLength()) { 171 destBits[i++] = B_TRANSPARENT_32_BIT.red; 172 destBits[i++] = B_TRANSPARENT_32_BIT.green; 173 destBits[i++] = B_TRANSPARENT_32_BIT.blue; 174 destBits[i++] = B_TRANSPARENT_32_BIT.alpha; 175 } 176 177 // scale and convert from B_CMAP8 to B_RGBA32 178 if (BIconUtils::ConvertFromCMAP8((uint8*)data, size, size, size, 179 dest) == B_OK) { 180 return B_OK; 181 } 182 } else { // assume B_CMAP8 183 // fill with transparent 184 uint8* destBits = (uint8*)dest->Bits(); 185 for (int32 i = 0; i < dest->BitsLength(); i++) 186 destBits[i] = B_TRANSPARENT_MAGIC_CMAP8; 187 } 188 189 // import bits into the middle of dest without scaling 190 // color space is converted from B_CMAP8 to B_RGBA32 191 float x = roundf((dest->Bounds().Width() - size) / 2); 192 float y = roundf((dest->Bounds().Height() - size) / 2); 193 return dest->ImportBits(data, (int32)length, size, B_CMAP8, 194 BPoint(0, 0), BPoint(x, y), BSize(size - 1, size - 1)); 195 } 196 197 198 status_t 199 BImageResources::GetIconResource(int32 id, const uint8** iconData, 200 size_t* iconSize) const 201 { 202 // try to load vector icon data from resources 203 size_t length = 0; 204 const void* data = LoadResource(B_VECTOR_ICON_TYPE, id, &length); 205 if (data == NULL) 206 return B_ERROR; 207 208 *iconData = (const uint8*)data; 209 *iconSize = length; 210 211 return B_OK; 212 } 213 214 215 image_id 216 BImageResources::find_image(void* memAddr) const 217 { 218 image_info info; 219 int32 cookie = 0; 220 while (get_next_image_info(0, &cookie, &info) == B_OK) { 221 if ((info.text <= memAddr 222 && (((uint8*)info.text)+info.text_size) > memAddr) 223 || (info.data <= memAddr 224 && (((uint8*)info.data)+info.data_size) > memAddr)) { 225 // Found the image. 226 return info.id; 227 } 228 } 229 230 return -1; 231 } 232 233 234 status_t 235 BImageResources::GetBitmapResource(type_code type, int32 id, 236 BBitmap** out) const 237 { 238 *out = NULL; 239 240 size_t len = 0; 241 const void* data = LoadResource(type, id, &len); 242 243 if (data == NULL) { 244 TRESPASS(); 245 return B_ERROR; 246 } 247 248 BMemoryIO stream(data, len); 249 250 // Try to read as an archived bitmap. 251 stream.Seek(0, SEEK_SET); 252 BMessage archive; 253 status_t result = archive.Unflatten(&stream); 254 if (result != B_OK) 255 return result; 256 257 *out = new BBitmap(&archive); 258 if (*out == NULL) 259 return B_ERROR; 260 261 result = (*out)->InitCheck(); 262 if (result != B_OK) { 263 delete *out; 264 *out = NULL; 265 } 266 267 return result; 268 } 269 270 271 static BLocker resLock; 272 static BImageResources* resources = NULL; 273 274 // This class is used as a static instance to delete the resources 275 // global object when the image is getting unloaded. 276 class _TTrackerCleanupResources { 277 public: 278 _TTrackerCleanupResources() 279 { 280 } 281 282 ~_TTrackerCleanupResources() 283 { 284 delete resources; 285 resources = NULL; 286 } 287 }; 288 289 290 namespace BPrivate { 291 292 static _TTrackerCleanupResources CleanupResources; 293 294 BImageResources* GetTrackerResources() 295 { 296 if (!resources) { 297 BAutolock lock(&resLock); 298 resources = new BImageResources(&resources); 299 } 300 301 return resources; 302 } 303 304 } // namespace BPrivate 305