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