/* * Copyright 2006, 2023, Haiku. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Stephan AĆmus <superstippi@gmx.de> * Zardshard */ #include "MessageExporter.h" #include <ByteOrder.h> #include <DataIO.h> #include <Message.h> #include <TypeConstants.h> #include "Container.h" #include "Defines.h" #include "Icon.h" #include "PathSourceShape.h" #include "ReferenceImage.h" #include "Shape.h" #include "Style.h" #include "Transformer.h" #include "VectorPath.h" // constructor MessageExporter::MessageExporter() { } // destructor MessageExporter::~MessageExporter() { } // Export status_t MessageExporter::Export(const Icon* icon, BPositionIO* stream) { status_t ret = B_OK; BMessage archive; const Container<VectorPath>* paths = icon->Paths(); const Container<Style>* styles = icon->Styles(); // paths if (ret == B_OK) { BMessage allPaths; int32 count = paths->CountItems(); for (int32 i = 0; i < count; i++) { VectorPath* path = paths->ItemAtFast(i); BMessage pathArchive; ret = _Export(path, &pathArchive); if (ret < B_OK) break; ret = allPaths.AddMessage("path", &pathArchive); if (ret < B_OK) break; } if (ret == B_OK) ret = archive.AddMessage("paths", &allPaths); } // styles if (ret == B_OK) { BMessage allStyles; int32 count = styles->CountItems(); for (int32 i = 0; i < count; i++) { Style* style = styles->ItemAtFast(i); BMessage styleArchive; ret = _Export(style, &styleArchive); if (ret < B_OK) break; ret = allStyles.AddMessage("style", &styleArchive); if (ret < B_OK) break; } if (ret == B_OK) ret = archive.AddMessage("styles", &allStyles); } // shapes if (ret == B_OK) { BMessage allShapes; const Container<Shape>* shapes = icon->Shapes(); int32 count = shapes->CountItems(); for (int32 i = 0; i < count; i++) { Shape* shape = shapes->ItemAtFast(i); BMessage shapeArchive; ret = _Export(shape, paths, styles, &shapeArchive); if (ret < B_OK) break; ret = allShapes.AddMessage("shape", &shapeArchive); if (ret < B_OK) break; } if (ret == B_OK) ret = archive.AddMessage("shapes", &allShapes); } // prepend the magic number to the file which // later tells us that this file is one of us if (ret == B_OK) { ssize_t size = sizeof(uint32); uint32 magic = B_HOST_TO_BENDIAN_INT32(kNativeIconMagicNumber); ssize_t written = stream->Write(&magic, size); if (written != size) { if (written < 0) ret = (status_t)written; else ret = B_IO_ERROR; } } if (ret == B_OK) ret = archive.Flatten(stream); return ret; } // MIMEType const char* MessageExporter::MIMEType() { return kNativeIconMimeType; } // #pragma mark - // _Export status_t MessageExporter::_Export(const VectorPath* path, BMessage* into) const { return path->Archive(into, true); } // _Export status_t MessageExporter::_Export(const Style* style, BMessage* into) const { return style->Archive(into, true); } // _Export status_t MessageExporter::_Export(const Shape* shape, const Container<VectorPath>* globalPaths, const Container<Style>* globalStyles, BMessage* into) const { status_t ret = B_OK; const PathSourceShape* pathSourceShape = dynamic_cast<const PathSourceShape*>(shape); if (pathSourceShape != NULL) { ret = into->AddInt32("type", PathSourceShape::archive_code); // NOTE: when the same path is used in two different // documents, and these are to be merged, each path // having a "globally unique" id would make it possible // to reference the same path across documents... // For now, we simply use the index of the path in the // globalPaths container. // index of used style if (ret == B_OK) { Style* style = pathSourceShape->Style(); ret = into->AddInt32("style ref", globalStyles->IndexOf(style)); } // indices of used paths if (ret == B_OK) { int32 count = pathSourceShape->Paths()->CountItems(); for (int32 i = 0; i < count; i++) { VectorPath* path = pathSourceShape->Paths()->ItemAtFast(i); ret = into->AddInt32("path ref", globalPaths->IndexOf(path)); if (ret < B_OK) break; } } } const ReferenceImage* referenceImage = dynamic_cast<const ReferenceImage*>(shape); if (referenceImage != NULL) { ret = into->AddInt32("type", ReferenceImage::archive_code); } // Shape properties if (ret == B_OK) ret = shape->Archive(into); return ret; }