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