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