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 TRESPASS(); 164 return B_ERROR; 165 } 166 167 if (dest->ColorSpace() == B_RGBA32) { 168 // fill with transparent 169 uint8* destBits = (uint8*)dest->Bits(); 170 int32 i = 0; 171 while (i < dest->BitsLength()) { 172 destBits[i++] = B_TRANSPARENT_32_BIT.red; 173 destBits[i++] = B_TRANSPARENT_32_BIT.green; 174 destBits[i++] = B_TRANSPARENT_32_BIT.blue; 175 destBits[i++] = B_TRANSPARENT_32_BIT.alpha; 176 } 177 178 // scale and convert from B_CMAP8 to B_RGBA32 179 if (BIconUtils::ConvertFromCMAP8((uint8*)data, size, size, size, 180 dest) == B_OK) { 181 return B_OK; 182 } 183 } else { // assume B_CMAP8 184 // fill with transparent 185 uint8* destBits = (uint8*)dest->Bits(); 186 for (int32 i = 0; i < dest->BitsLength(); i++) 187 destBits[i] = B_TRANSPARENT_MAGIC_CMAP8; 188 } 189 190 // import bits into the middle of dest without scaling 191 // color space is converted from B_CMAP8 to B_RGBA32 192 float x = roundf((dest->Bounds().Width() - size) / 2); 193 float y = roundf((dest->Bounds().Height() - size) / 2); 194 return dest->ImportBits(data, (int32)length, size, B_CMAP8, 195 BPoint(0, 0), BPoint(x, y), BSize(size - 1, size - 1)); 196 } 197 198 199 status_t 200 BImageResources::GetIconResource(int32 id, const uint8** iconData, 201 size_t* iconSize) const 202 { 203 // try to load vector icon data from resources 204 size_t length = 0; 205 const void* data = LoadResource(B_VECTOR_ICON_TYPE, id, &length); 206 if (data == NULL) 207 return B_ERROR; 208 209 *iconData = (const uint8*)data; 210 *iconSize = length; 211 212 return B_OK; 213 } 214 215 216 image_id 217 BImageResources::find_image(void* memAddr) const 218 { 219 image_info info; 220 int32 cookie = 0; 221 while (get_next_image_info(0, &cookie, &info) == B_OK) { 222 if ((info.text <= memAddr 223 && (((uint8*)info.text)+info.text_size) > memAddr) 224 || (info.data <= memAddr 225 && (((uint8*)info.data)+info.data_size) > memAddr)) { 226 // Found the image. 227 return info.id; 228 } 229 } 230 231 return -1; 232 } 233 234 235 status_t 236 BImageResources::GetBitmapResource(type_code type, int32 id, 237 BBitmap** out) const 238 { 239 *out = NULL; 240 241 size_t len = 0; 242 const void* data = LoadResource(type, id, &len); 243 244 if (data == NULL) { 245 TRESPASS(); 246 return B_ERROR; 247 } 248 249 BMemoryIO stream(data, len); 250 251 // Try to read as an archived bitmap. 252 stream.Seek(0, SEEK_SET); 253 BMessage archive; 254 status_t result = archive.Unflatten(&stream); 255 if (result != B_OK) 256 return result; 257 258 *out = new BBitmap(&archive); 259 if (*out == NULL) 260 return B_ERROR; 261 262 result = (*out)->InitCheck(); 263 if (result != B_OK) { 264 delete *out; 265 *out = NULL; 266 } 267 268 return result; 269 } 270 271 272 static BLocker resLock; 273 static BImageResources* resources = NULL; 274 275 // This class is used as a static instance to delete the resources 276 // global object when the image is getting unloaded. 277 class _TTrackerCleanupResources { 278 public: 279 _TTrackerCleanupResources() 280 { 281 } 282 283 ~_TTrackerCleanupResources() 284 { 285 delete resources; 286 resources = NULL; 287 } 288 }; 289 290 291 namespace BPrivate { 292 293 static _TTrackerCleanupResources CleanupResources; 294 295 BImageResources* GetTrackerResources() 296 { 297 if (!resources) { 298 BAutolock lock(&resLock); 299 resources = new BImageResources(&resources); 300 } 301 302 return resources; 303 } 304 305 } // namespace BPrivate 306