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