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