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
24using std::nothrow;
25
26
27ReferenceImage::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
52ReferenceImage::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
72ReferenceImage::ReferenceImage(BMessage* archive)
73	: Shape(new (nothrow) _ICON_NAMESPACE Style()),
74	fPath(NULL)
75{
76	Unarchive(archive);
77}
78
79
80ReferenceImage::~ReferenceImage()
81{
82}
83
84
85// #pragma mark -
86
87
88status_t
89ReferenceImage::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
123status_t
124ReferenceImage::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
151PropertyObject*
152ReferenceImage::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
162bool
163ReferenceImage::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
177status_t
178ReferenceImage::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
194void
195ReferenceImage::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