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