xref: /haiku/src/apps/icon-o-matic/import_export/message/MessageExporter.cpp (revision e81a954787e50e56a7f06f72705b7859b6ab06d1)
1 /*
2  * Copyright 2006, 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 #include "MessageExporter.h"
10 
11 #include <ByteOrder.h>
12 #include <DataIO.h>
13 #include <Message.h>
14 #include <TypeConstants.h>
15 
16 #include "Defines.h"
17 #include "Icon.h"
18 #include "PathContainer.h"
19 #include "Shape.h"
20 #include "Style.h"
21 #include "StyleContainer.h"
22 #include "Transformer.h"
23 #include "VectorPath.h"
24 
25 // constructor
26 MessageExporter::MessageExporter()
27 {
28 }
29 
30 // destructor
31 MessageExporter::~MessageExporter()
32 {
33 }
34 
35 // Export
36 status_t
37 MessageExporter::Export(const Icon* icon, BPositionIO* stream)
38 {
39 	status_t ret = B_OK;
40 	BMessage archive;
41 
42 	PathContainer* paths = icon->Paths();
43 	StyleContainer* styles = icon->Styles();
44 
45 	// paths
46 	if (ret == B_OK) {
47 		BMessage allPaths;
48 		int32 count = paths->CountPaths();
49 		for (int32 i = 0; i < count; i++) {
50 			VectorPath* path = paths->PathAtFast(i);
51 			BMessage pathArchive;
52 			ret = _Export(path, &pathArchive);
53 			if (ret < B_OK)
54 				break;
55 			ret = allPaths.AddMessage("path", &pathArchive);
56 			if (ret < B_OK)
57 				break;
58 		}
59 
60 		if (ret == B_OK)
61 			ret = archive.AddMessage("paths", &allPaths);
62 	}
63 
64 	// styles
65 	if (ret == B_OK) {
66 		BMessage allStyles;
67 		int32 count = styles->CountStyles();
68 		for (int32 i = 0; i < count; i++) {
69 			Style* style = styles->StyleAtFast(i);
70 			BMessage styleArchive;
71 			ret = _Export(style, &styleArchive);
72 			if (ret < B_OK)
73 				break;
74 			ret = allStyles.AddMessage("style", &styleArchive);
75 			if (ret < B_OK)
76 				break;
77 		}
78 
79 		if (ret == B_OK)
80 			ret = archive.AddMessage("styles", &allStyles);
81 	}
82 
83 	// shapes
84 	if (ret == B_OK) {
85 		BMessage allShapes;
86 		ShapeContainer* shapes = icon->Shapes();
87 		int32 count = shapes->CountShapes();
88 		for (int32 i = 0; i < count; i++) {
89 			Shape* shape = shapes->ShapeAtFast(i);
90 			BMessage shapeArchive;
91 			ret = _Export(shape, paths, styles, &shapeArchive);
92 			if (ret < B_OK)
93 				break;
94 			ret = allShapes.AddMessage("shape", &shapeArchive);
95 			if (ret < B_OK)
96 				break;
97 		}
98 
99 		if (ret == B_OK)
100 			ret = archive.AddMessage("shapes", &allShapes);
101 	}
102 
103 	// prepend the magic number to the file which
104 	// later tells us that this file is one of us
105 	if (ret == B_OK) {
106 		ssize_t size = sizeof(uint32);
107 		uint32 magic = B_HOST_TO_BENDIAN_INT32(kNativeIconMagicNumber);
108 		ssize_t written = stream->Write(&magic, size);
109 		if (written != size) {
110 			if (written < 0)
111 				ret = (status_t)written;
112 			else
113 				ret = B_IO_ERROR;
114 		}
115 	}
116 
117 	if (ret == B_OK)
118 		ret = archive.Flatten(stream);
119 
120 	return ret;
121 }
122 
123 // MIMEType
124 const char*
125 MessageExporter::MIMEType()
126 {
127 	return kNativeIconMimeType;
128 }
129 
130 // #pragma mark -
131 
132 // _Export
133 status_t
134 MessageExporter::_Export(const VectorPath* path, BMessage* into) const
135 {
136 	return path->Archive(into, true);
137 }
138 
139 // _Export
140 status_t
141 MessageExporter::_Export(const Style* style, BMessage* into) const
142 {
143 	return style->Archive(into, true);
144 }
145 
146 // _Export
147 status_t
148 MessageExporter::_Export(const Shape* shape,
149 						 const PathContainer* globalPaths,
150 						 const StyleContainer* globalStyles,
151 						 BMessage* into) const
152 {
153 	// NOTE: when the same path is used in two different
154 	// documents, and these are to be merged, each path
155 	// having a "globally unique" id would make it possible
156 	// to reference the same path across documents...
157 	// For now, we simply use the index of the path in the
158 	// globalPaths container.
159 
160 	// index of used style
161 	Style* style = shape->Style();
162 	status_t ret = into->AddInt32("style ref", globalStyles->IndexOf(style));
163 
164 	// indices of used paths
165 	if (ret == B_OK) {
166 		int32 count = shape->Paths()->CountPaths();
167 		for (int32 i = 0; i < count; i++) {
168 			VectorPath* path = shape->Paths()->PathAtFast(i);
169 			ret = into->AddInt32("path ref", globalPaths->IndexOf(path));
170 			if (ret < B_OK)
171 				break;
172 		}
173 	}
174 
175 	// Shape properties
176 	if (ret == B_OK)
177 		ret = shape->Archive(into);
178 
179 	return ret;
180 }
181 
182