xref: /haiku/src/libs/icon/message/MessageImporter.cpp (revision 68ea01249e1e2088933cb12f9c28d4e5c5d1c9ef)
1 /*
2  * Copyright 2006-2010, Haiku. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *		Stephan Aßmus <superstippi@gmx.de>
7  */
8 
9 
10 #include "MessageImporter.h"
11 
12 #include <new>
13 #include <stdio.h>
14 
15 #include <Archivable.h>
16 #include <ByteOrder.h>
17 #include <DataIO.h>
18 #include <Message.h>
19 
20 #include "Defines.h"
21 #include "Icon.h"
22 #include "PathContainer.h"
23 #include "Shape.h"
24 #include "Style.h"
25 #include "StyleContainer.h"
26 #include "VectorPath.h"
27 
28 
29 using std::nothrow;
30 
31 
32 MessageImporter::MessageImporter()
33 #ifdef ICON_O_MATIC
34 	: Importer()
35 #endif
36 {
37 }
38 
39 
40 MessageImporter::~MessageImporter()
41 {
42 }
43 
44 
45 status_t
46 MessageImporter::Import(Icon* icon, BPositionIO* stream)
47 {
48 #ifdef ICON_O_MATIC
49 	status_t ret = Init(icon);
50 	if (ret < B_OK) {
51 		printf("MessageImporter::Import() - "
52 			   "Init() error: %s\n", strerror(ret));
53 		return ret;
54 	}
55 #else
56 	status_t ret;
57 #endif
58 
59 	uint32 magic = 0;
60 	ssize_t size = sizeof(magic);
61 	off_t position = stream->Position();
62 	ssize_t read = stream->Read(&magic, size);
63 	if (read != size) {
64 		if (read < 0)
65 			ret = (status_t)read;
66 		else
67 			ret = B_IO_ERROR;
68 		return ret;
69 	}
70 
71 	if (B_BENDIAN_TO_HOST_INT32(magic) != kNativeIconMagicNumber) {
72 		// this might be an old native icon file, where
73 		// we didn't prepend the magic number yet, seek back
74 		if (stream->Seek(position, SEEK_SET) != position) {
75 			printf("MessageImporter::Import() - "
76 				   "failed to seek back to beginning of stream\n");
77 			return B_IO_ERROR;
78 		}
79 	}
80 
81 	BMessage archive;
82 	ret = archive.Unflatten(stream);
83 	if (ret != B_OK)
84 		return ret;
85 
86 	// paths
87 	PathContainer* paths = icon->Paths();
88 	ret = _ImportPaths(&archive, paths);
89 	if (ret < B_OK) {
90 		printf("MessageImporter::Import() - "
91 			   "error importing paths: %s\n", strerror(ret));
92 		return ret;
93 	}
94 
95 	// styles
96 	StyleContainer* styles = icon->Styles();
97 	ret = _ImportStyles(&archive, styles);
98 	if (ret < B_OK) {
99 		printf("MessageImporter::Import() - "
100 			   "error importing styles: %s\n", strerror(ret));
101 		return ret;
102 	}
103 
104 	// shapes
105 	ret = _ImportShapes(&archive, paths, styles, icon->Shapes());
106 	if (ret < B_OK) {
107 		printf("MessageImporter::Import() - "
108 			   "error importing shapes: %s\n", strerror(ret));
109 		return ret;
110 	}
111 
112 	return B_OK;
113 }
114 
115 
116 // #pragma mark -
117 
118 
119 status_t
120 MessageImporter::_ImportPaths(const BMessage* archive,
121 	PathContainer* paths) const
122 {
123 	BMessage allPaths;
124 	status_t ret = archive->FindMessage("paths", &allPaths);
125 	if (ret < B_OK)
126 		return ret;
127 
128 	BMessage pathArchive;
129 	for (int32 i = 0;
130 		 allPaths.FindMessage("path", i, &pathArchive) == B_OK; i++) {
131 		VectorPath* path = new (nothrow) VectorPath(&pathArchive);
132 		if (!path || !paths->AddPath(path)) {
133 			delete path;
134 			ret = B_NO_MEMORY;
135 		}
136 		if (ret < B_OK)
137 			break;
138 	}
139 
140 	return ret;
141 }
142 
143 
144 status_t
145 MessageImporter::_ImportStyles(const BMessage* archive,
146 	StyleContainer* styles) const
147 {
148 	BMessage allStyles;
149 	status_t ret = archive->FindMessage("styles", &allStyles);
150 	if (ret < B_OK)
151 		return ret;
152 
153 	BMessage styleArchive;
154 	for (int32 i = 0;
155 		 allStyles.FindMessage("style", i, &styleArchive) == B_OK; i++) {
156 		Style* style = new (nothrow) Style(&styleArchive);
157 		if (!style || !styles->AddStyle(style)) {
158 			delete style;
159 			ret = B_NO_MEMORY;
160 		}
161 		if (ret < B_OK)
162 			break;
163 	}
164 
165 	return ret;
166 }
167 
168 
169 status_t
170 MessageImporter::_ImportShapes(const BMessage* archive, PathContainer* paths,
171 	StyleContainer* styles, ShapeContainer* shapes) const
172 {
173 	BMessage allShapes;
174 	status_t ret = archive->FindMessage("shapes", &allShapes);
175 	if (ret < B_OK)
176 		return ret;
177 
178 	BMessage shapeArchive;
179 	for (int32 i = 0;
180 		 allShapes.FindMessage("shape", i, &shapeArchive) == B_OK; i++) {
181 		// find the right style
182 		int32 styleIndex;
183 		if (shapeArchive.FindInt32("style ref", &styleIndex) < B_OK) {
184 			printf("MessageImporter::_ImportShapes() - "
185 				   "Shape %" B_PRId32 " doesn't reference a Style!", i);
186 			continue;
187 		}
188 #ifdef ICON_O_MATIC
189 		Style* style = styles->StyleAt(StyleIndexFor(styleIndex));
190 #else
191 		Style* style = styles->StyleAt(styleIndex);
192 #endif
193 		if (!style) {
194 			printf("MessageImporter::_ImportShapes() - "
195 				   "Shape %" B_PRId32 " wants Style %" B_PRId32 ", which does not exist\n",
196 				i, styleIndex);
197 			continue;
198 		}
199 
200 		// create shape
201 		Shape* shape = new (nothrow) Shape(style);
202 		if (!shape || shape->InitCheck() < B_OK || !shapes->AddShape(shape)) {
203 			delete shape;
204 			ret = B_NO_MEMORY;
205 		}
206 		if (ret < B_OK)
207 			break;
208 
209 		// find the referenced paths
210 		int32 pathIndex;
211 		for (int32 j = 0;
212 			 shapeArchive.FindInt32("path ref", j, &pathIndex) == B_OK;
213 			 j++) {
214 #ifdef ICON_O_MATIC
215 			VectorPath* path = paths->PathAt(PathIndexFor(pathIndex));
216 #else
217 			VectorPath* path = paths->PathAt(pathIndex);
218 #endif
219 			if (!path) {
220 				printf("MessageImporter::_ImportShapes() - "
221 					   "Shape %" B_PRId32 " referenced path %" B_PRId32 ", "
222 					   "which does not exist\n", i, pathIndex);
223 				continue;
224 			}
225 			shape->Paths()->AddPath(path);
226 		}
227 
228 		// Shape properties
229 		if (ret == B_OK)
230 			shape->Unarchive(&shapeArchive);
231 	}
232 
233 	return ret;
234 }
235