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 } 69 70 71 ReferenceImage::ReferenceImage(BMessage* archive) 72 : Shape(new (nothrow) _ICON_NAMESPACE Style()), 73 fPath(NULL) 74 { 75 Unarchive(archive); 76 } 77 78 79 ReferenceImage::~ReferenceImage() 80 { 81 } 82 83 84 // #pragma mark - 85 86 87 status_t 88 ReferenceImage::Unarchive(BMessage* archive) 89 { 90 // IconObject properties 91 status_t ret = IconObject::Unarchive(archive); 92 if (ret < B_OK) 93 return ret; 94 95 // read transformation 96 const double* matrix; 97 ssize_t dataSize; 98 ret = archive->FindData("transformation", B_DOUBLE_TYPE, 99 (const void**) &matrix, &dataSize); 100 if (ret < B_OK) 101 return ret; 102 if (dataSize != Transformable::matrix_size * sizeof(double)) 103 return B_BAD_VALUE; 104 LoadFrom(matrix); 105 106 BBitmap* bitmap = dynamic_cast<BBitmap*>(BBitmap::Instantiate(archive)); 107 if (bitmap == NULL) 108 return B_ERROR; 109 SetImage(bitmap); 110 111 return B_OK; 112 } 113 114 115 status_t 116 ReferenceImage::Archive(BMessage* into, bool deep) const 117 { 118 status_t ret = IconObject::Archive(into, deep); 119 if (ret < B_OK) 120 return ret; 121 122 // transformation 123 int32 size = Transformable::matrix_size; 124 double matrix[size]; 125 StoreTo(matrix); 126 ret = into->AddData("transformation", B_DOUBLE_TYPE, 127 matrix, size * sizeof(double)); 128 if (ret < B_OK) 129 return ret; 130 131 // image 132 ret = Style()->Bitmap()->Archive(into, deep); 133 return ret; 134 } 135 136 137 PropertyObject* 138 ReferenceImage::MakePropertyObject() const 139 { 140 PropertyObject* object = IconObject::MakePropertyObject(); 141 142 object->AddProperty(new IntProperty(PROPERTY_ALPHA, Style()->Alpha(), 0, 255)); 143 144 return object; 145 } 146 147 148 bool 149 ReferenceImage::SetToPropertyObject(const PropertyObject* object) 150 { 151 AutoNotificationSuspender _(this); 152 IconObject::SetToPropertyObject(object); 153 154 Style()->SetAlpha(object->Value(PROPERTY_ALPHA, (int32) Style()->Alpha())); 155 156 return HasPendingNotifications(); 157 } 158 159 160 // #pragma mark - 161 162 163 status_t 164 ReferenceImage::InitCheck() const 165 { 166 status_t status = Shape::InitCheck(); 167 if (status != B_OK) 168 return status; 169 170 if (Style() == NULL || Style()->Bitmap() == NULL) 171 return B_NO_MEMORY; 172 173 return B_OK; 174 } 175 176 177 // #pragma mark - 178 179 180 void 181 ReferenceImage::SetImage(BBitmap* image) 182 { 183 if (fPath != NULL) { 184 Paths()->MakeEmpty(); 185 delete fPath; 186 fPath = NULL; 187 } 188 189 if (image != NULL) { 190 // Update style 191 Style()->SetBitmap(image); 192 193 // Update shape 194 fPath = new (nothrow) VectorPath(); 195 if (fPath == NULL) 196 return; 197 198 double width = (int) Style()->Bitmap()->Bounds().Width() + 1; 199 double height = (int) Style()->Bitmap()->Bounds().Height() + 1; 200 fPath->AddPoint(BPoint(0, 0)); 201 fPath->AddPoint(BPoint(0, height)); 202 fPath->AddPoint(BPoint(width, height)); 203 fPath->AddPoint(BPoint(width, 0)); 204 fPath->SetClosed(true); 205 Paths()->AddPath(fPath); 206 } 207 } 208 209 #endif // ICON_O_MATIC 210 211