1 /* 2 * Copyright 2006, 2023, Haiku. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 * Zardshard 8 */ 9 10 #ifdef ICON_O_MATIC 11 #include "ReferenceImage.h" 12 13 #include <algorithm> 14 #include <new> 15 16 #include <Bitmap.h> 17 #include <Message.h> 18 19 #include "CommonPropertyIDs.h" 20 #include "Property.h" 21 #include "PropertyObject.h" 22 #include "Style.h" 23 24 using std::nothrow; 25 26 27 ReferenceImage::ReferenceImage(BBitmap* image) 28 : Shape(new (nothrow) _ICON_NAMESPACE Style()), 29 fPath(NULL) 30 { 31 if (Style() == NULL) 32 return; 33 Style()->ReleaseReference(); 34 // The shape constructor acquired a reference 35 36 SetName("<reference image>"); 37 SetImage(image); 38 39 double width = (int) Style()->Bitmap()->Bounds().Width() + 1; 40 double height = (int) Style()->Bitmap()->Bounds().Height() + 1; 41 42 // Scale to fill canvas 43 double longerSide = std::max(width, height); 44 ScaleBy(BPoint(0, 0), 64/longerSide, 64/longerSide); 45 46 // Center 47 Transform(&width, &height); 48 TranslateBy(BPoint((64-width)/2, (64-height)/2)); 49 } 50 51 52 ReferenceImage::ReferenceImage(const ReferenceImage& other) 53 : Shape(new (nothrow) _ICON_NAMESPACE Style()), 54 fPath(NULL) 55 { 56 if (Style() == NULL) 57 return; 58 Style()->ReleaseReference(); 59 // The shape constructor acquired a reference 60 61 BBitmap* bitmap = new (nothrow) BBitmap(other.Style()->Bitmap()); 62 if (bitmap == NULL) 63 return; 64 65 SetName(other.Name()); 66 SetImage(bitmap); 67 SetTransform(other); 68 Style()->SetAlpha(other.Style()->Alpha()); 69 } 70 71 72 ReferenceImage::ReferenceImage(BMessage* archive) 73 : Shape(new (nothrow) _ICON_NAMESPACE Style()), 74 fPath(NULL) 75 { 76 Unarchive(archive); 77 } 78 79 80 ReferenceImage::~ReferenceImage() 81 { 82 } 83 84 85 // #pragma mark - 86 87 88 status_t 89 ReferenceImage::Unarchive(BMessage* archive) 90 { 91 // IconObject properties 92 status_t ret = IconObject::Unarchive(archive); 93 if (ret < B_OK) 94 return ret; 95 96 // transformation 97 const double* matrix; 98 ssize_t dataSize; 99 ret = archive->FindData("transformation", B_DOUBLE_TYPE, 100 (const void**) &matrix, &dataSize); 101 if (ret < B_OK) 102 return ret; 103 if (dataSize != Transformable::matrix_size * sizeof(double)) 104 return B_BAD_VALUE; 105 LoadFrom(matrix); 106 107 // image 108 BBitmap* bitmap = dynamic_cast<BBitmap*>(BBitmap::Instantiate(archive)); 109 if (bitmap == NULL) 110 return B_ERROR; 111 SetImage(bitmap); 112 113 // alpha 114 uint8 alpha; 115 if(archive->FindUInt8("alpha", &alpha) < B_OK) 116 alpha = 255; 117 Style()->SetAlpha(alpha); 118 119 return B_OK; 120 } 121 122 123 status_t 124 ReferenceImage::Archive(BMessage* into, bool deep) const 125 { 126 status_t ret = IconObject::Archive(into, deep); 127 if (ret < B_OK) 128 return ret; 129 130 // transformation 131 int32 size = Transformable::matrix_size; 132 double matrix[size]; 133 StoreTo(matrix); 134 ret = into->AddData("transformation", B_DOUBLE_TYPE, 135 matrix, size * sizeof(double)); 136 if (ret < B_OK) 137 return ret; 138 139 // image 140 ret = Style()->Bitmap()->Archive(into, deep); 141 if (ret < B_OK) 142 return ret; 143 144 // alpha 145 ret = into->AddUInt8("alpha", Style()->Alpha()); 146 147 return ret; 148 } 149 150 151 PropertyObject* 152 ReferenceImage::MakePropertyObject() const 153 { 154 PropertyObject* object = IconObject::MakePropertyObject(); 155 156 object->AddProperty(new IntProperty(PROPERTY_ALPHA, Style()->Alpha(), 0, 255)); 157 158 return object; 159 } 160 161 162 bool 163 ReferenceImage::SetToPropertyObject(const PropertyObject* object) 164 { 165 AutoNotificationSuspender _(this); 166 IconObject::SetToPropertyObject(object); 167 168 Style()->SetAlpha(object->Value(PROPERTY_ALPHA, (int32) Style()->Alpha())); 169 170 return HasPendingNotifications(); 171 } 172 173 174 // #pragma mark - 175 176 177 status_t 178 ReferenceImage::InitCheck() const 179 { 180 status_t status = Shape::InitCheck(); 181 if (status != B_OK) 182 return status; 183 184 if (Style() == NULL || Style()->Bitmap() == NULL) 185 return B_NO_MEMORY; 186 187 return B_OK; 188 } 189 190 191 // #pragma mark - 192 193 194 void 195 ReferenceImage::SetImage(BBitmap* image) 196 { 197 if (fPath != NULL) { 198 Paths()->MakeEmpty(); 199 delete fPath; 200 fPath = NULL; 201 } 202 203 if (image != NULL) { 204 // Update style 205 Style()->SetBitmap(image); 206 207 // Update shape 208 fPath = new (nothrow) VectorPath(); 209 if (fPath == NULL) 210 return; 211 212 double width = (int) Style()->Bitmap()->Bounds().Width() + 1; 213 double height = (int) Style()->Bitmap()->Bounds().Height() + 1; 214 fPath->AddPoint(BPoint(0, 0)); 215 fPath->AddPoint(BPoint(0, height)); 216 fPath->AddPoint(BPoint(width, height)); 217 fPath->AddPoint(BPoint(width, 0)); 218 fPath->SetClosed(true); 219 Paths()->AddItem(fPath); 220 } 221 } 222 223 #endif // ICON_O_MATIC 224 225