xref: /haiku/src/libs/icon/shape/ReferenceImage.cpp (revision e1c4049fed1047bdb957b0529e1921e97ef94770)
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