diff --git a/src/apps/icon-o-matic/CanvasView.cpp b/src/apps/icon-o-matic/CanvasView.cpp index 277cf6deb8..381c98e425 100644 --- a/src/apps/icon-o-matic/CanvasView.cpp +++ b/src/apps/icon-o-matic/CanvasView.cpp @@ -435,7 +435,7 @@ void CanvasView::_DrawInto(BView* view, BRect updateRect) { if (fDirtyIconArea.IsValid()) { - fRenderer->Render(fDirtyIconArea); + fRenderer->Render(fDirtyIconArea, true); fDirtyIconArea.Set(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN); } diff --git a/src/apps/icon-o-matic/IconEditorApp.cpp b/src/apps/icon-o-matic/IconEditorApp.cpp index d667ce90ce..a6a6f5e3f6 100644 --- a/src/apps/icon-o-matic/IconEditorApp.cpp +++ b/src/apps/icon-o-matic/IconEditorApp.cpp @@ -1,6 +1,10 @@ /* * Copyright 2006, 2011, Stephan Aßmus . + * Copyright 2023 Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. + * + * Authors: + * Zardshard */ @@ -26,6 +30,7 @@ #include "Defines.h" #include "MainWindow.h" #include "SavePanel.h" +#include "ShapeListView.h" #undef B_TRANSLATION_CONTEXT @@ -123,6 +128,9 @@ IconEditorApp::MessageReceived(BMessage* message) MainWindow* window; if (message->FindPointer("window", (void**)&window) == B_OK) openMessage.AddPointer("window", window); + bool referenceImage; + if (message->FindBool("reference image", &referenceImage) == B_OK) + openMessage.AddBool("reference image", referenceImage); fOpenPanel->SetMessage(&openMessage); fOpenPanel->Show(); break; @@ -216,6 +224,9 @@ IconEditorApp::RefsReceived(BMessage* message) bool append; if (message->FindBool("append", &append) != B_OK) append = false; + bool referenceImage; + if (message->FindBool("reference image", &referenceImage) != B_OK) + referenceImage = false; MainWindow* window; if (message->FindPointer("window", (void**)&window) != B_OK) window = NULL; @@ -223,11 +234,15 @@ IconEditorApp::RefsReceived(BMessage* message) if (append && window == NULL) return; entry_ref ref; - if (append) { + if (append || referenceImage) { if (!window->Lock()) return; - for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) - window->Open(ref, true); + for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { + if (append) + window->Open(ref, true); + if (referenceImage) + window->AddReferenceImage(ref); + } window->Unlock(); } else { for (int32 i = 0; message->FindRef("refs", i, &ref) == B_OK; i++) { diff --git a/src/apps/icon-o-matic/Jamfile b/src/apps/icon-o-matic/Jamfile index b2d19f473f..632d1780dd 100644 --- a/src/apps/icon-o-matic/Jamfile +++ b/src/apps/icon-o-matic/Jamfile @@ -82,6 +82,8 @@ Application Icon-O-Matic : # icon/shape PathContainer.cpp + PathSourceShape.cpp + ReferenceImage.cpp Shape.cpp ShapeContainer.cpp VectorPath.cpp diff --git a/src/apps/icon-o-matic/MainWindow.cpp b/src/apps/icon-o-matic/MainWindow.cpp index bd28990332..fc5a60fd11 100644 --- a/src/apps/icon-o-matic/MainWindow.cpp +++ b/src/apps/icon-o-matic/MainWindow.cpp @@ -1,6 +1,10 @@ /* * Copyright 2006-2011, Stephan Aßmus . + * Copyright 2023, Haiku, Inc. * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Zardshard */ #include "MainWindow.h" @@ -9,6 +13,7 @@ #include #include +#include #include #include #include @@ -25,8 +30,10 @@ #include #include #include +#include #include #include +#include #include "support_ui.h" @@ -73,6 +80,8 @@ #include "Icon.h" #include "MultipleManipulatorState.h" #include "PathManipulator.h" +#include "PathSourceShape.h" +#include "ReferenceImage.h" #include "Shape.h" #include "ShapeContainer.h" #include "ShapeListView.h" @@ -207,6 +216,24 @@ MainWindow::MessageReceived(BMessage* message) case B_REFS_RECEIVED: case B_SIMPLE_DATA: + { + entry_ref ref; + if (message->FindRef("refs", &ref) != B_OK) + break; + + // Check if this is best represented by a ReferenceImage + BMimeType type; + if (BMimeType::GuessMimeType(&ref, &type) == B_OK) { + BMimeType superType; + if (type.GetSupertype(&superType) == B_OK + && superType == BMimeType("image") + && !(type == BMimeType("image/svg+xml")) + && !(type == BMimeType("image/x-hvif"))) { + AddReferenceImage(ref); + break; + } + } + // If our icon is empty, open the file in this window, // otherwise forward to the application which will open // it in another window, unless we append. @@ -214,9 +241,7 @@ MainWindow::MessageReceived(BMessage* message) if (fDocument->Icon()->Styles()->CountStyles() == 0 && fDocument->Icon()->Paths()->CountPaths() == 0 && fDocument->Icon()->Shapes()->CountShapes() == 0) { - entry_ref ref; - if (message->FindRef("refs", &ref) == B_OK) - Open(ref); + Open(ref); break; } if (modifiers() & B_SHIFT_KEY) { @@ -226,6 +251,7 @@ MainWindow::MessageReceived(BMessage* message) } be_app->PostMessage(message); break; + } case B_PASTE: case B_MIME_DATA: @@ -272,15 +298,23 @@ MainWindow::MessageReceived(BMessage* message) } case MSG_OPEN: + { // If our icon is empty, we want the icon to open in this // window. - if (fDocument->Icon()->Styles()->CountStyles() == 0 + bool emptyDocument = fDocument->Icon()->Styles()->CountStyles() == 0 && fDocument->Icon()->Paths()->CountPaths() == 0 - && fDocument->Icon()->Shapes()->CountShapes() == 0) { + && fDocument->Icon()->Shapes()->CountShapes() == 0; + + bool openingReferenceImage; + if (message->FindBool("reference image", &openingReferenceImage) != B_OK) + openingReferenceImage = false; + + if (emptyDocument || openingReferenceImage) message->AddPointer("window", this); - } + be_app->PostMessage(message); break; + } case MSG_SAVE: case MSG_EXPORT: @@ -414,11 +448,9 @@ MainWindow::MessageReceived(BMessage* message) style = fDocument->Icon()->Styles()->StyleAt(0); } - Shape* shape = new (nothrow) Shape(style); - Shape* shapes[1]; - shapes[0] = shape; + PathSourceShape* shape = new (nothrow) PathSourceShape(style); AddShapesCommand* shapeCommand = new (nothrow) AddShapesCommand( - fDocument->Icon()->Shapes(), shapes, 1, + fDocument->Icon()->Shapes(), (Shape**) &shape, 1, fDocument->Icon()->Shapes()->CountShapes(), fDocument->Selection()); @@ -824,6 +856,29 @@ MainWindow::Open(const BMessenger& externalObserver, const uint8* data, } +void +MainWindow::AddReferenceImage(const entry_ref& ref) +{ + BBitmap* image = BTranslationUtils::GetBitmap(&ref); + if (image == NULL) + return; + Shape* shape = new (nothrow) ReferenceImage(image); + if (shape == NULL) + return; + + AddShapesCommand* shapeCommand = new (nothrow) AddShapesCommand( + fDocument->Icon()->Shapes(), &shape, 1, + fDocument->Icon()->Shapes()->CountShapes(), + fDocument->Selection()); + if (shapeCommand == NULL) { + delete shape; + return; + } + + fDocument->CommandStack()->Perform(shapeCommand); +} + + void MainWindow::SetIcon(Icon* icon) { diff --git a/src/apps/icon-o-matic/MainWindow.h b/src/apps/icon-o-matic/MainWindow.h index 95f435f6b2..71c6879901 100644 --- a/src/apps/icon-o-matic/MainWindow.h +++ b/src/apps/icon-o-matic/MainWindow.h @@ -1,6 +1,10 @@ /* * Copyright 2006-2010, Stephan Aßmus . + * Copyright 2023, Haiku, Inc. * All rights reserved. Distributed under the terms of the MIT License. + * + * Authors: + * Zardshard */ #ifndef MAIN_WINDOW_H #define MAIN_WINDOW_H @@ -73,6 +77,7 @@ public: bool append = false); void Open(const BMessenger& externalObserver, const uint8* data, size_t size); + void AddReferenceImage(const entry_ref& ref); void StoreSettings(BMessage* archive); void RestoreSettings(const BMessage* archive); diff --git a/src/apps/icon-o-matic/document/IconObject.cpp b/src/apps/icon-o-matic/document/IconObject.cpp index 9ba83f8a44..825466118e 100644 --- a/src/apps/icon-o-matic/document/IconObject.cpp +++ b/src/apps/icon-o-matic/document/IconObject.cpp @@ -63,7 +63,7 @@ IconObject::SelectedChanged() // Unarchive status_t -IconObject::Unarchive(const BMessage* archive) +IconObject::Unarchive(BMessage* archive) { if (!archive) return B_BAD_VALUE; diff --git a/src/apps/icon-o-matic/document/IconObject.h b/src/apps/icon-o-matic/document/IconObject.h index 77c93f3978..0a29412473 100644 --- a/src/apps/icon-o-matic/document/IconObject.h +++ b/src/apps/icon-o-matic/document/IconObject.h @@ -31,7 +31,7 @@ class IconObject : public Observable, virtual void SelectedChanged(); // IconObject - virtual status_t Unarchive(const BMessage* archive); + virtual status_t Unarchive(BMessage* archive); virtual status_t Archive(BMessage* into, bool deep = true) const; diff --git a/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.cpp b/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.cpp index 82b8541538..3a813dbd9a 100644 --- a/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.cpp +++ b/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.cpp @@ -30,6 +30,9 @@ name_for_id(int32 id) name = B_TRANSLATE("Name"); break; + case PROPERTY_ALPHA: + name = B_TRANSLATE("Alpha"); + break; case PROPERTY_OPACITY: name = B_TRANSLATE("Opacity"); break; diff --git a/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.h b/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.h index fddca619f2..77e623383a 100644 --- a/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.h +++ b/src/apps/icon-o-matic/generic/property/CommonPropertyIDs.h @@ -14,7 +14,8 @@ enum { PROPERTY_NAME = 'name', - PROPERTY_OPACITY = 'alpa', + PROPERTY_ALPHA = 'alpa', + PROPERTY_OPACITY = 'opac', PROPERTY_COLOR = 'colr', PROPERTY_WIDTH = 'wdth', diff --git a/src/apps/icon-o-matic/gui/IconView.cpp b/src/apps/icon-o-matic/gui/IconView.cpp index 8487c53760..f425315696 100644 --- a/src/apps/icon-o-matic/gui/IconView.cpp +++ b/src/apps/icon-o-matic/gui/IconView.cpp @@ -57,7 +57,7 @@ void IconView::Draw(BRect updateRect) { if (fDirtyIconArea.IsValid()) { - fRenderer->Render(fDirtyIconArea); + fRenderer->Render(fDirtyIconArea, false); fDirtyIconArea.Set(LONG_MAX, LONG_MAX, LONG_MIN, LONG_MIN); } diff --git a/src/apps/icon-o-matic/gui/PathListView.cpp b/src/apps/icon-o-matic/gui/PathListView.cpp index faf8876cb5..29426023cd 100644 --- a/src/apps/icon-o-matic/gui/PathListView.cpp +++ b/src/apps/icon-o-matic/gui/PathListView.cpp @@ -26,6 +26,7 @@ #include "CommandStack.h" #include "MovePathsCommand.h" #include "Observer.h" +#include "PathSourceShape.h" #include "RemovePathsCommand.h" #include "ReversePathCommand.h" #include "RotatePathIndicesCommand.h" @@ -242,7 +243,7 @@ public: // ShapePathListener - void SetShape(Shape* shape) + void SetShape(PathSourceShape* shape) { if (fShape == shape) return; @@ -263,8 +264,8 @@ public: } private: - PathListView* fListView; - Shape* fShape; + PathListView* fListView; + PathSourceShape* fShape; }; @@ -868,8 +869,8 @@ PathListView::SetCurrentShape(Shape* shape) if (fCurrentShape == shape) return; - fCurrentShape = shape; - fShapePathListener->SetShape(shape); + fCurrentShape = dynamic_cast(shape); + fShapePathListener->SetShape(fCurrentShape); _UpdateMarks(); } diff --git a/src/apps/icon-o-matic/gui/PathListView.h b/src/apps/icon-o-matic/gui/PathListView.h index 7c93448526..6282a532cd 100644 --- a/src/apps/icon-o-matic/gui/PathListView.h +++ b/src/apps/icon-o-matic/gui/PathListView.h @@ -18,6 +18,7 @@ class BMenuItem; _BEGIN_ICON_NAMESPACE class VectorPath; + class PathSourceShape; class Shape; class ShapeContainer; _END_ICON_NAMESPACE @@ -74,7 +75,7 @@ class PathListView : public SimpleListView, void SetMenu(BMenu* menu); void SetCurrentShape(Shape* shape); - Shape* CurrentShape() const + PathSourceShape* CurrentShape() const { return fCurrentShape; } private: @@ -106,7 +107,7 @@ class PathListView : public SimpleListView, ShapeContainer* fShapeContainer; CommandStack* fCommandStack; - Shape* fCurrentShape; + PathSourceShape* fCurrentShape; // those path items will be marked that // are referenced by this shape diff --git a/src/apps/icon-o-matic/gui/ShapeListView.cpp b/src/apps/icon-o-matic/gui/ShapeListView.cpp index d536a7357f..b333bacc8d 100644 --- a/src/apps/icon-o-matic/gui/ShapeListView.cpp +++ b/src/apps/icon-o-matic/gui/ShapeListView.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2006-2012, Haiku, Inc. All rights reserved. + * Copyright 2006-2012, 2023, Haiku, Inc. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus + * Zardshard */ #include "ShapeListView.h" @@ -27,9 +28,12 @@ #include "CommandStack.h" #include "CompoundCommand.h" #include "FreezeTransformationCommand.h" +#include "MainWindow.h" #include "MoveShapesCommand.h" #include "Observer.h" +#include "ReferenceImage.h" #include "PathContainer.h" +#include "PathSourceShape.h" #include "RemoveShapesCommand.h" #include "ResetTransformationCommand.h" #include "Selection.h" @@ -214,8 +218,19 @@ ShapeListView::MessageReceived(BMessage* message) if (count < 0) break; + BList pathSourceShapes; + + for (int i = 0; i < count; i++) { + Shape* shape = (Shape*) shapes.ItemAtFast(i); + if (dynamic_cast(shape) != NULL) + pathSourceShapes.AddItem(shape); + } + + count = pathSourceShapes.CountItems(); + FreezeTransformationCommand* command - = new FreezeTransformationCommand((Shape**)shapes.Items(), + = new FreezeTransformationCommand( + (PathSourceShape**)pathSourceShapes.Items(), count); fCommandStack->Perform(command); @@ -239,27 +254,51 @@ ShapeListView::MakeDragMessage(BMessage* message) const ShapeListItem* item = dynamic_cast( ItemAt(CurrentSelection(i))); if (item != NULL && item->shape != NULL) { - message->AddPointer("shape", (void*)item->shape); - - // Add archives of everything this Shape uses - BMessage archive; - - BMessage styleArchive; - item->shape->Style()->Archive(&styleArchive, true); - archive.AddMessage("style", &styleArchive); + PathSourceShape* pathSourceShape = dynamic_cast(item->shape); + if (pathSourceShape != NULL) { + message->AddInt32("type", PathSourceShape::archive_code); - PathContainer* paths = item->shape->Paths(); - for (int32 j = 0; j < paths->CountPaths(); j++) { - BMessage pathArchive; - paths->PathAt(j)->Archive(&pathArchive, true); - archive.AddMessage("path", &pathArchive); + PathSourceShape* shape = pathSourceShape; + message->AddPointer("shape", (void*)shape); + + // Add archives of everything this Shape uses + BMessage archive; + + BMessage styleArchive; + shape->Style()->Archive(&styleArchive, true); + archive.AddMessage("style", &styleArchive); + + PathContainer* paths = shape->Paths(); + for (int32 j = 0; j < paths->CountPaths(); j++) { + BMessage pathArchive; + paths->PathAt(j)->Archive(&pathArchive, true); + archive.AddMessage("path", &pathArchive); + } + + BMessage shapeArchive; + shape->Archive(&shapeArchive, true); + archive.AddMessage("shape", &shapeArchive); + + message->AddMessage("shape archive", &archive); + continue; } - BMessage shapeArchive; - item->shape->Archive(&shapeArchive, true); - archive.AddMessage("shape", &shapeArchive); + ReferenceImage* referenceImage = dynamic_cast(item->shape); + if (referenceImage != NULL) { + message->AddInt32("type", ReferenceImage::archive_code); - message->AddMessage("shape archive", &archive); + message->AddPointer("shape", (void*)referenceImage); + + // Add archives of everything this Shape uses + BMessage archive; + + BMessage shapeArchive; + referenceImage->Archive(&shapeArchive, true); + archive.AddMessage("shape", &shapeArchive); + + message->AddMessage("shape archive", &archive); + continue; + } } else break; } @@ -300,87 +339,108 @@ ShapeListView::HandleDropMessage(const BMessage* message, int32 dropIndex) BList paths; BList shapes; while (true) { - BMessage archive; - if (message->FindMessage("shape archive", index, &archive) != B_OK) + int32 type; + if (message->FindInt32("type", index, &type) != B_OK) break; - // Extract the shape archive - BMessage shapeArchive; - if (archive.FindMessage("shape", &shapeArchive) != B_OK) - break; - - // Extract the style - BMessage styleArchive; - if (archive.FindMessage("style", &styleArchive) != B_OK) - break; - - Style* style = new Style(&styleArchive); - if (style == NULL) - break; - - Style* styleToAssign = style; - // Try to find an existing style that is the same as the extracted - // style and use that one instead. - for (int32 i = 0; i < fStyleContainer->CountStyles(); i++) { - Style* other = fStyleContainer->StyleAtFast(i); - if (*other == *style) { - styleToAssign = other; - delete style; - style = NULL; + if (type == PathSourceShape::archive_code) { + BMessage archive; + if (message->FindMessage("shape archive", index, &archive) != B_OK) break; - } - } - - if (style != NULL && !styles.AddItem(style)) { - delete style; - break; - } - // Create the shape using the given style - Shape* shape = new(std::nothrow) Shape(styleToAssign); - if (shape == NULL) - break; + // Extract the shape archive + BMessage shapeArchive; + if (archive.FindMessage("shape", &shapeArchive) != B_OK) + break; - if (shape->Unarchive(&shapeArchive) != B_OK - || !shapes.AddItem(shape)) { - delete shape; - if (style != NULL) { - styles.RemoveItem(style); - delete style; - } - break; - } - - // Extract the paths - int pathIndex = 0; - while (true) { - BMessage pathArchive; - if (archive.FindMessage("path", pathIndex, &pathArchive) != B_OK) + // Extract the style + BMessage styleArchive; + if (archive.FindMessage("style", &styleArchive) != B_OK) break; - - VectorPath* path = new(nothrow) VectorPath(&pathArchive); - if (path == NULL) + + Style* style = new Style(&styleArchive); + if (style == NULL) break; - - VectorPath* pathToInclude = path; - for (int32 i = 0; i < fPathContainer->CountPaths(); i++) { - VectorPath* other = fPathContainer->PathAtFast(i); - if (*other == *path) { - pathToInclude = other; - delete path; - path = NULL; + + Style* styleToAssign = style; + // Try to find an existing style that is the same as the extracted + // style and use that one instead. + for (int32 i = 0; i < fStyleContainer->CountStyles(); i++) { + Style* other = fStyleContainer->StyleAtFast(i); + if (*other == *style) { + styleToAssign = other; + delete style; + style = NULL; break; } } - - if (path != NULL && !paths.AddItem(path)) { - delete path; + + if (style != NULL && !styles.AddItem(style)) { + delete style; break; } - - shape->Paths()->AddPath(pathToInclude); - - pathIndex++; + + // Create the shape using the given style + PathSourceShape* shape = new(std::nothrow) PathSourceShape(styleToAssign); + if (shape == NULL) + break; + + if (shape->Unarchive(&shapeArchive) != B_OK + || !shapes.AddItem(shape)) { + delete shape; + if (style != NULL) { + styles.RemoveItem(style); + delete style; + } + break; + } + + // Extract the paths + int pathIndex = 0; + while (true) { + BMessage pathArchive; + if (archive.FindMessage("path", pathIndex, &pathArchive) != B_OK) + break; + + VectorPath* path = new(nothrow) VectorPath(&pathArchive); + if (path == NULL) + break; + + VectorPath* pathToInclude = path; + for (int32 i = 0; i < fPathContainer->CountPaths(); i++) { + VectorPath* other = fPathContainer->PathAtFast(i); + if (*other == *path) { + pathToInclude = other; + delete path; + path = NULL; + break; + } + } + + if (path != NULL && !paths.AddItem(path)) { + delete path; + break; + } + + shape->Paths()->AddPath(pathToInclude); + + pathIndex++; + } + } else if (type == ReferenceImage::archive_code) { + BMessage archive; + if (message->FindMessage("shape archive", index, &archive) != B_OK) + break; + + BMessage shapeArchive; + if (archive.FindMessage("shape", &shapeArchive) != B_OK) + break; + + ReferenceImage* shape = new (std::nothrow) ReferenceImage(&shapeArchive); + if (shape == NULL) + break; + + if (shapes.AddItem(shape) != B_OK) + break; } index++; @@ -462,7 +522,7 @@ ShapeListView::CopyItems(BList& items, int32 toIndex) for (int32 i = 0; i < count; i++) { ShapeListItem* item = dynamic_cast((BListItem*)items.ItemAtFast(i)); - shapes[i] = item ? new(nothrow) Shape(*item->shape) : NULL; + shapes[i] = item ? item->shape->Clone() : NULL; } AddShapesCommand* command = new(nothrow) AddShapesCommand(fShapeContainer, @@ -612,6 +672,10 @@ ShapeListView::SetMenu(BMenu* menu) fAddWidthPathAndStyleMI = new BMenuItem( B_TRANSLATE("Add with path & style"), message); + message = new BMessage(MSG_OPEN); + message->AddBool("reference image", true); + fAddReferenceImageMI = new BMenuItem(B_TRANSLATE("Add reference image"), message); + fDuplicateMI = new BMenuItem(B_TRANSLATE("Duplicate"), new BMessage(MSG_DUPLICATE)); fResetTransformationMI = new BMenuItem(B_TRANSLATE("Reset transformation"), @@ -630,10 +694,13 @@ ShapeListView::SetMenu(BMenu* menu) fMenu->AddSeparatorItem(); + fMenu->AddItem(fAddReferenceImageMI); + + fMenu->AddSeparatorItem(); + fMenu->AddItem(fDuplicateMI); fMenu->AddItem(fResetTransformationMI); fMenu->AddItem(fFreezeTransformationMI); - fMenu->AddSeparatorItem(); fMenu->AddItem(fRemoveMI); @@ -753,6 +820,21 @@ ShapeListView::_UpdateMenu() fResetTransformationMI->SetEnabled(gotSelection); fFreezeTransformationMI->SetEnabled(gotSelection); fRemoveMI->SetEnabled(gotSelection); + + if (gotSelection) { + bool hasPathSourceShape = false; + + int32 count = CountSelectedItems(); + for (int32 i = 0; i < count; i++) { + ShapeListItem* item + = dynamic_cast(ItemAt(CurrentSelection(i))); + bool isPathSourceShape + = item ? dynamic_cast(item->shape) != NULL : false; + hasPathSourceShape |= isPathSourceShape; + } + + fFreezeTransformationMI->SetEnabled(hasPathSourceShape); + } } diff --git a/src/apps/icon-o-matic/gui/ShapeListView.h b/src/apps/icon-o-matic/gui/ShapeListView.h index 9e92069b15..43d090c059 100644 --- a/src/apps/icon-o-matic/gui/ShapeListView.h +++ b/src/apps/icon-o-matic/gui/ShapeListView.h @@ -1,9 +1,10 @@ /* - * Copyright 2006-2007, Haiku. + * Copyright 2006-2007, 2023, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus + * Zardshard */ #ifndef SHAPE_LIST_VIEW_H #define SHAPE_LIST_VIEW_H @@ -30,6 +31,7 @@ _USING_ICON_NAMESPACE enum { MSG_ADD_SHAPE = 'adsh', + MSG_ADD_REFERENCE_IMAGE = 'aimg', }; class ShapeListView : public SimpleListView, @@ -95,6 +97,7 @@ class ShapeListView : public SimpleListView, BMenuItem* fAddWidthPathMI; BMenuItem* fAddWidthStyleMI; BMenuItem* fAddWidthPathAndStyleMI; + BMenuItem* fAddReferenceImageMI; BMenuItem* fDuplicateMI; BMenuItem* fResetTransformationMI; BMenuItem* fFreezeTransformationMI; diff --git a/src/apps/icon-o-matic/gui/StyleListView.cpp b/src/apps/icon-o-matic/gui/StyleListView.cpp index 9565b7bf49..eaa132436b 100644 --- a/src/apps/icon-o-matic/gui/StyleListView.cpp +++ b/src/apps/icon-o-matic/gui/StyleListView.cpp @@ -25,6 +25,7 @@ #include "CommandStack.h" #include "GradientTransformable.h" #include "MoveStylesCommand.h" +#include "PathSourceShape.h" #include "RemoveStylesCommand.h" #include "Style.h" #include "Observer.h" @@ -236,7 +237,7 @@ public: } // ShapeStyleListener - void SetShape(Shape* shape) + void SetShape(PathSourceShape* shape) { if (fShape == shape) return; @@ -250,14 +251,14 @@ public: fShape->AddListener(this); } - Shape* CurrentShape() const + PathSourceShape* CurrentShape() const { return fShape; } private: - StyleListView* fListView; - Shape* fShape; + StyleListView* fListView; + PathSourceShape* fShape; }; @@ -769,11 +770,13 @@ StyleListView::SetCurrentColor(CurrentColor* color) void StyleListView::SetCurrentShape(Shape* shape) { - if (fCurrentShape == shape) + PathSourceShape* pathSourceShape = dynamic_cast(shape); + + if (fCurrentShape == pathSourceShape) return; - fCurrentShape = shape; - fShapeListener->SetShape(shape); + fCurrentShape = pathSourceShape; + fShapeListener->SetShape(pathSourceShape); _UpdateMarks(); } diff --git a/src/apps/icon-o-matic/gui/StyleListView.h b/src/apps/icon-o-matic/gui/StyleListView.h index 9945b8d965..707de7e468 100644 --- a/src/apps/icon-o-matic/gui/StyleListView.h +++ b/src/apps/icon-o-matic/gui/StyleListView.h @@ -19,6 +19,7 @@ class ShapeStyleListener; class StyleListItem; _BEGIN_ICON_NAMESPACE + class PathSourceShape; class Shape; class ShapeContainer; class ShapeListener; @@ -72,7 +73,7 @@ public: void SetCurrentColor(CurrentColor* color); void SetCurrentShape(Shape* shape); - Shape* CurrentShape() const + PathSourceShape* CurrentShape() const { return fCurrentShape; } private: @@ -93,7 +94,7 @@ private: CommandStack* fCommandStack; CurrentColor* fCurrentColor; - Shape* fCurrentShape; + PathSourceShape* fCurrentShape; // the style item will be marked that // is referenced by this shape diff --git a/src/apps/icon-o-matic/gui/TransformerListView.cpp b/src/apps/icon-o-matic/gui/TransformerListView.cpp index 22c5adbaf1..4cb658f26d 100644 --- a/src/apps/icon-o-matic/gui/TransformerListView.cpp +++ b/src/apps/icon-o-matic/gui/TransformerListView.cpp @@ -24,6 +24,7 @@ #include "AddTransformersCommand.h" #include "CommandStack.h" #include "MoveTransformersCommand.h" +#include "ReferenceImage.h" #include "RemoveTransformersCommand.h" #include "Transformer.h" #include "TransformerFactory.h" @@ -386,20 +387,31 @@ TransformerListView::SetMenu(BMenu* menu) return; BMenu* addMenu = new BMenu(B_TRANSLATE("Add")); - int32 cookie = 0; - uint32 type; - BString name; - while (TransformerFactory::NextType(&cookie, &type, &name)) { - // TODO: Disable the "Transformation" and "Perspective" transformers - // since they are not very useful or even implemented at all. - if (name == B_TRANSLATE("Transformation") - || name == B_TRANSLATE("Perspective")) - continue; - // End of TODO. - BMessage* message = new BMessage(MSG_ADD_TRANSFORMER); - message->AddInt32("type", type); - addMenu->AddItem(new BMenuItem(name.String(), message)); - } + + // Keep translated strings that were brought in from another file +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "Transformation" + BMessage* message = new BMessage(MSG_ADD_TRANSFORMER); + message->AddInt32("type", CONTOUR_TRANSFORMER); + fContourMI = new BMenuItem(B_TRANSLATE("Contour"), message); + + message = new BMessage(MSG_ADD_TRANSFORMER); + message->AddInt32("type", STROKE_TRANSFORMER); + fStrokeMI = new BMenuItem(B_TRANSLATE("Stroke"), message); + + // message = new BMessage(MSG_ADD_TRANSFORMER); + // message->AddInt32("type", PERSPECTIVE_TRANSFORMER); + // fPerspectiveMI = new BMenuItem(B_TRANSLATE("Perspective"), message); + + // message = new BMessage(MSG_ADD_TRANSFORMER); + // message->AddInt32("type", AFFINE_TRANSFORMER); + // fTransformationMI = new BMenuItem(B_TRANSLATE("Transformation"), message); +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "Icon-O-Matic-TransformersList" + + addMenu->AddItem(fContourMI); + addMenu->AddItem(fStrokeMI); + addMenu->SetTargetForItems(this); fMenu->AddItem(addMenu); @@ -480,4 +492,8 @@ void TransformerListView::_UpdateMenu() { fMenu->SetEnabled(fShape != NULL); + + bool isReferenceImage = dynamic_cast(fShape) != NULL; + fContourMI->SetEnabled(!isReferenceImage); + fStrokeMI->SetEnabled(!isReferenceImage); } diff --git a/src/apps/icon-o-matic/gui/TransformerListView.h b/src/apps/icon-o-matic/gui/TransformerListView.h index b08171718d..1c043db7a9 100644 --- a/src/apps/icon-o-matic/gui/TransformerListView.h +++ b/src/apps/icon-o-matic/gui/TransformerListView.h @@ -14,6 +14,7 @@ class BMenu; +class BMenuItem; class CommandStack; class TransformerItem; class Selection; @@ -79,6 +80,8 @@ class TransformerListView : public SimpleListView, CommandStack* fCommandStack; BMenu* fMenu; + BMenuItem* fContourMI; + BMenuItem* fStrokeMI; }; #endif // TRANSFORMER_LIST_VIEW_H diff --git a/src/apps/icon-o-matic/import_export/bitmap/BitmapExporter.cpp b/src/apps/icon-o-matic/import_export/bitmap/BitmapExporter.cpp index fc0f9a2aaf..9fafb75c07 100644 --- a/src/apps/icon-o-matic/import_export/bitmap/BitmapExporter.cpp +++ b/src/apps/icon-o-matic/import_export/bitmap/BitmapExporter.cpp @@ -15,6 +15,8 @@ #include "Icon.h" #include "IconRenderer.h" +#include "ReferenceImage.h" + // constructor BitmapExporter::BitmapExporter(uint32 size) @@ -53,7 +55,7 @@ BitmapExporter::Export(const Icon* icon, BPositionIO* stream) IconRenderer renderer(&bitmap); renderer.SetIcon(icon); renderer.SetScale(fSize / 64.0); - renderer.Render(); + renderer.Render(false); // renderer.Demultiply(&bitmap); // save bitmap to translator diff --git a/src/apps/icon-o-matic/import_export/flat_icon/FlatIconExporter.cpp b/src/apps/icon-o-matic/import_export/flat_icon/FlatIconExporter.cpp index a81c398615..96b5658164 100644 --- a/src/apps/icon-o-matic/import_export/flat_icon/FlatIconExporter.cpp +++ b/src/apps/icon-o-matic/import_export/flat_icon/FlatIconExporter.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2006, Haiku. All rights reserved. + * Copyright 2006, 2023, Haiku. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus + * Zardshard */ #include "FlatIconExporter.h" @@ -24,7 +25,9 @@ #include "LittleEndianBuffer.h" #include "PathCommandQueue.h" #include "PathContainer.h" +#include "PathSourceShape.h" #include "PerspectiveTransformer.h" +#include "ReferenceImage.h" #include "Shape.h" #include "StrokeTransformer.h" #include "Style.h" @@ -477,7 +480,7 @@ _WriteTransformer(LittleEndianBuffer& buffer, Transformer* t) // _WritePathSourceShape static bool -_WritePathSourceShape(LittleEndianBuffer& buffer, Shape* shape, +_WritePathSourceShape(LittleEndianBuffer& buffer, PathSourceShape* shape, StyleContainer* styles, PathContainer* paths) { // find out which style this shape uses @@ -575,16 +578,31 @@ FlatIconExporter::_WriteShapes(LittleEndianBuffer& buffer, PathContainer* paths, ShapeContainer* shapes) { - if (shapes->CountShapes() > 255) - return B_RESULT_NOT_REPRESENTABLE; - uint8 shapeCount = min_c(255, shapes->CountShapes()); - if (!buffer.Write(shapeCount)) - return B_NO_MEMORY; + uint32 shapeCount = shapes->CountShapes(); + // Count the number of exportable shapes + uint32 pathShapeCount = 0; for (uint32 i = 0; i < shapeCount; i++) { Shape* shape = shapes->ShapeAtFast(i); - if (!_WritePathSourceShape(buffer, shape, styles, paths)) - return B_ERROR; + if (dynamic_cast(shape) != NULL) + pathShapeCount++; + } + + // Write number of exportable shapes + if (pathShapeCount > 255) + return B_RESULT_NOT_REPRESENTABLE; + if (!buffer.Write((uint8) pathShapeCount)) + return B_NO_MEMORY; + + // Export each shape + for (uint32 i = 0; i < shapeCount; i++) { + Shape* shape = shapes->ShapeAtFast(i); + + PathSourceShape* pathSourceShape = dynamic_cast(shape); + if (pathSourceShape != NULL) { + if (!_WritePathSourceShape(buffer, pathSourceShape, styles, paths)) + return B_ERROR; + } } return B_OK; diff --git a/src/apps/icon-o-matic/import_export/message/MessageExporter.cpp b/src/apps/icon-o-matic/import_export/message/MessageExporter.cpp index f1a6b5cb37..f14a87441f 100644 --- a/src/apps/icon-o-matic/import_export/message/MessageExporter.cpp +++ b/src/apps/icon-o-matic/import_export/message/MessageExporter.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2006, Haiku. All rights reserved. + * Copyright 2006, 2023, Haiku. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus + * Zardshard */ #include "MessageExporter.h" @@ -16,6 +17,8 @@ #include "Defines.h" #include "Icon.h" #include "PathContainer.h" +#include "PathSourceShape.h" +#include "ReferenceImage.h" #include "Shape.h" #include "Style.h" #include "StyleContainer.h" @@ -150,26 +153,40 @@ MessageExporter::_Export(const Shape* shape, const StyleContainer* globalStyles, BMessage* into) const { - // 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. + status_t ret = B_OK; - // index of used style - Style* style = shape->Style(); - status_t ret = into->AddInt32("style ref", globalStyles->IndexOf(style)); + const PathSourceShape* pathSourceShape = dynamic_cast(shape); + if (pathSourceShape != NULL) { + ret = into->AddInt32("type", PathSourceShape::archive_code); - // indices of used paths - if (ret == B_OK) { - int32 count = shape->Paths()->CountPaths(); - for (int32 i = 0; i < count; i++) { - VectorPath* path = shape->Paths()->PathAtFast(i); - ret = into->AddInt32("path ref", globalPaths->IndexOf(path)); - if (ret < B_OK) - break; + // 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()->CountPaths(); + for (int32 i = 0; i < count; i++) { + VectorPath* path = pathSourceShape->Paths()->PathAtFast(i); + ret = into->AddInt32("path ref", globalPaths->IndexOf(path)); + if (ret < B_OK) + break; + } + } + } + + const ReferenceImage* referenceImage = dynamic_cast(shape); + if (referenceImage != NULL) { + ret = into->AddInt32("type", ReferenceImage::archive_code); } // Shape properties diff --git a/src/apps/icon-o-matic/import_export/styled_text/StyledTextImporter.cpp b/src/apps/icon-o-matic/import_export/styled_text/StyledTextImporter.cpp index b525503572..dd8efa4bb2 100644 --- a/src/apps/icon-o-matic/import_export/styled_text/StyledTextImporter.cpp +++ b/src/apps/icon-o-matic/import_export/styled_text/StyledTextImporter.cpp @@ -29,7 +29,7 @@ #include "Defines.h" #include "Icon.h" #include "PathContainer.h" -#include "Shape.h" +#include "PathSourceShape.h" #include "Style.h" #include "StyleContainer.h" #include "VectorPath.h" @@ -45,7 +45,7 @@ using std::nothrow; class ShapeIterator : public BShapeIterator { public: - ShapeIterator(Icon *icon, Shape *to, BPoint offset, const char *name); + ShapeIterator(Icon *icon, PathSourceShape *to, BPoint offset, const char *name); ~ShapeIterator() {}; virtual status_t IterateMoveTo(BPoint *point); @@ -58,7 +58,7 @@ class ShapeIterator : public BShapeIterator { void NextPath(); Icon *fIcon; - Shape *fShape; + PathSourceShape *fShape; VectorPath *fPath; BPoint fOffset; const char *fName; @@ -66,7 +66,7 @@ class ShapeIterator : public BShapeIterator { bool fHasLastPoint; }; -ShapeIterator::ShapeIterator(Icon *icon, Shape *to, BPoint offset, +ShapeIterator::ShapeIterator(Icon *icon, PathSourceShape *to, BPoint offset, const char *name) { CALLED(); @@ -328,7 +328,7 @@ StyledTextImporter::_Import(Icon* icon, const char *text, text_run_array *runs) if (glyph.Bounds().IsValid()) { //offset.x += glyph.Bounds().Width(); offset.x += charWidth; - Shape* shape = new (nothrow) Shape(NULL); + PathSourceShape* shape = new (nothrow) PathSourceShape(NULL); if (shape == NULL) return B_NO_MEMORY; shape->SetName(glyphName.String()); diff --git a/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp b/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp index 3ae2257d1e..611f33c5ce 100644 --- a/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp +++ b/src/apps/icon-o-matic/import_export/svg/DocumentBuilder.cpp @@ -19,7 +19,7 @@ #include "GradientTransformable.h" #include "Icon.h" #include "PathContainer.h" -#include "Shape.h" +#include "PathSourceShape.h" #include "ShapeContainer.h" #include "StrokeTransformer.h" #include "Style.h" @@ -112,9 +112,12 @@ printf("scale: %f\n", scale); // clean up styles and paths (remove duplicates) int32 count = icon->Shapes()->CountShapes(); for (int32 i = 1; i < count; i++) { - Shape* shape = icon->Shapes()->ShapeAtFast(i); + PathSourceShape* shape = dynamic_cast(icon->Shapes()->ShapeAtFast(i)); + if (shape == NULL) + continue; + Style* style = shape->Style(); - if (!style) + if (style == NULL) continue; int32 styleIndex = icon->Styles()->IndexOf(style); for (int32 j = 0; j < styleIndex; j++) { @@ -134,7 +137,7 @@ printf("scale: %f\n", scale); // AddVertexSource status_t -AddPathsFromVertexSource(Icon* icon, Shape* shape, NSVGshape* svgShape) +AddPathsFromVertexSource(Icon* icon, PathSourceShape* shape, NSVGshape* svgShape) { //printf("AddPathsFromVertexSource(pathID = %ld)\n", index); @@ -194,7 +197,7 @@ status_t DocumentBuilder::_AddShape(NSVGshape* svgShape, bool outline, const Transformable& transform, Icon* icon) { - Shape* shape = new (nothrow) Shape(NULL); + PathSourceShape* shape = new (nothrow) PathSourceShape(NULL); if (!shape || !icon->Shapes()->AddShape(shape)) { delete shape; return B_NO_MEMORY; @@ -245,7 +248,7 @@ DocumentBuilder::_AddShape(NSVGshape* svgShape, bool outline, } } else { paint = &svgShape->fill; -#if 0 // FIXME filling rule are missing from Shape class +#if 0 // FIXME filling rule are missing from PathSourceShape class if (svgShape->fillRule == NSVG_FILLRULE_EVENODD) shape->SetFillingRule(FILL_MODE_EVEN_ODD); else diff --git a/src/apps/icon-o-matic/import_export/svg/SVGExporter.cpp b/src/apps/icon-o-matic/import_export/svg/SVGExporter.cpp index 061bb336e0..82291855e3 100644 --- a/src/apps/icon-o-matic/import_export/svg/SVGExporter.cpp +++ b/src/apps/icon-o-matic/import_export/svg/SVGExporter.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2006, Haiku. All rights reserved. + * Copyright 2006, 2023, Haiku. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus + * Zardshard */ #include @@ -19,6 +20,7 @@ #include "Icon.h" #include "GradientTransformable.h" +#include "PathSourceShape.h" #include "Shape.h" #include "StrokeTransformer.h" #include "Style.h" @@ -200,14 +202,19 @@ convert_cap_mode_svg(agg::line_cap_e mode) status_t SVGExporter::_ExportShape(const Shape* shape, BPositionIO* stream) { - if (shape->MaxVisibilityScale() < 1.0 - || shape->MinVisibilityScale() > 1.0) { + if (!shape->Visible(1.0)) { // don't export shapes which are not visible at the // default scale return B_OK; } - const Style* style = shape->Style(); + // only render PathSourceShapes + const PathSourceShape* pathSourceShape = dynamic_cast(shape); + if (pathSourceShape == NULL) + return B_OK; + + + const Style* style = pathSourceShape->Style(); char color[64]; status_t ret = _GetFill(style, color, stream); @@ -230,7 +237,7 @@ SVGExporter::_ExportShape(const Shape* shape, BPositionIO* stream) // hack to see if this is an outline shape StrokeTransformer* stroke - = dynamic_cast(shape->TransformerAt(0)); + = dynamic_cast(pathSourceShape->TransformerAt(0)); if (stroke) { helper << "style=\"fill:none; stroke:" << color; if (!style->Gradient() && style->Color().alpha < 255) { @@ -259,8 +266,8 @@ SVGExporter::_ExportShape(const Shape* shape, BPositionIO* stream) append_float(helper, style->Color().alpha / 255.0); } -// if (shape->FillingRule() == FILL_MODE_EVEN_ODD && -// shape->Paths()->CountPaths() > 1) +// if (pathSourceShape->FillingRule() == FILL_MODE_EVEN_ODD && +// pathSourceShape->Paths()->CountPaths() > 1) // helper << "; fill-rule:evenodd"; helper << "\"\n"; @@ -272,9 +279,9 @@ SVGExporter::_ExportShape(const Shape* shape, BPositionIO* stream) if (ret < B_OK) return ret; - int32 count = shape->Paths()->CountPaths(); + int32 count = pathSourceShape->Paths()->CountPaths(); for (int32 i = 0; i < count; i++) { - VectorPath* path = shape->Paths()->PathAtFast(i); + VectorPath* path = pathSourceShape->Paths()->PathAtFast(i); if (i > 0) { helper << "\n "; @@ -340,9 +347,9 @@ SVGExporter::_ExportShape(const Shape* shape, BPositionIO* stream) } helper << "\"\n"; - if (!shape->IsIdentity()) { + if (!pathSourceShape->IsIdentity()) { helper << " transform=\""; - _AppendMatrix(shape, helper); + _AppendMatrix(pathSourceShape, helper); helper << "\n"; } diff --git a/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.cpp b/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.cpp index 105479227a..802e0db59a 100644 --- a/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.cpp +++ b/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.cpp @@ -16,7 +16,7 @@ #include #include "GradientTransformable.h" -#include "Shape.h" +#include "PathSourceShape.h" #include "Style.h" #include "VectorPath.h" @@ -29,10 +29,10 @@ using std::nothrow; // constructor FreezeTransformationCommand::FreezeTransformationCommand( - Shape** const shapes, + PathSourceShape** const shapes, int32 count) : Command(), - fShapes(shapes && count > 0 ? new (nothrow) Shape*[count] : NULL), + fShapes(shapes && count > 0 ? new (nothrow) PathSourceShape*[count] : NULL), fOriginalTransformations(count > 0 ? new (nothrow) double[ count * Transformable::matrix_size] : NULL), @@ -41,7 +41,7 @@ FreezeTransformationCommand::FreezeTransformationCommand( if (!fShapes || !fOriginalTransformations) return; - memcpy(fShapes, shapes, sizeof(Shape*) * fCount); + memcpy(fShapes, shapes, sizeof(PathSourceShape*) * fCount); bool initOk = false; @@ -128,7 +128,7 @@ FreezeTransformationCommand::GetName(BString& name) // _ApplyTransformation void -FreezeTransformationCommand::_ApplyTransformation(Shape* shape, +FreezeTransformationCommand::_ApplyTransformation(PathSourceShape* shape, const Transformable& transform) { // apply inverse of old shape transformation to every assigned path diff --git a/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.h b/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.h index 82c452c44d..0e10415b32 100644 --- a/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.h +++ b/src/apps/icon-o-matic/shape/commands/FreezeTransformationCommand.h @@ -14,7 +14,7 @@ _BEGIN_ICON_NAMESPACE - class Shape; + class PathSourceShape; class Transformable; _END_ICON_NAMESPACE @@ -24,7 +24,7 @@ _USING_ICON_NAMESPACE class FreezeTransformationCommand : public Command { public: FreezeTransformationCommand( - Shape** const shapes, + PathSourceShape** const shapes, int32 count); virtual ~FreezeTransformationCommand(); @@ -36,10 +36,10 @@ class FreezeTransformationCommand : public Command { virtual void GetName(BString& name); private: - void _ApplyTransformation(Shape* shape, + void _ApplyTransformation(PathSourceShape* shape, const Transformable& transform); - Shape** fShapes; + PathSourceShape** fShapes; double* fOriginalTransformations; int32 fCount; }; diff --git a/src/apps/icon-o-matic/shape/commands/RemovePathsCommand.cpp b/src/apps/icon-o-matic/shape/commands/RemovePathsCommand.cpp index c1a69c9325..3bcf59169f 100644 --- a/src/apps/icon-o-matic/shape/commands/RemovePathsCommand.cpp +++ b/src/apps/icon-o-matic/shape/commands/RemovePathsCommand.cpp @@ -15,6 +15,7 @@ #include #include "PathContainer.h" +#include "PathSourceShape.h" #include "Shape.h" #include "VectorPath.h" @@ -44,7 +45,8 @@ RemovePathsCommand::RemovePathsCommand(PathContainer* container, if (paths[i]) { int32 listenerCount = paths[i]->CountListeners(); for (int32 j = 0; j < listenerCount; j++) { - Shape* shape = dynamic_cast(paths[i]->ListenerAtFast(j)); + PathSourceShape* shape + = dynamic_cast(paths[i]->ListenerAtFast(j)); if (shape) fInfos[i].shapes.AddItem((void*)shape); } @@ -82,7 +84,7 @@ RemovePathsCommand::Perform() fContainer->RemovePath(fInfos[i].path); int32 shapeCount = fInfos[i].shapes.CountItems(); for (int32 j = 0; j < shapeCount; j++) { - Shape* shape = (Shape*)fInfos[i].shapes.ItemAtFast(j); + PathSourceShape* shape = (PathSourceShape*)fInfos[i].shapes.ItemAtFast(j); shape->Paths()->RemovePath(fInfos[i].path); } } @@ -108,7 +110,7 @@ RemovePathsCommand::Undo() fContainer->RemovePath(fInfos[j].path); int32 shapeCount = fInfos[j].shapes.CountItems(); for (int32 k = 0; k < shapeCount; k++) { - Shape* shape = (Shape*)fInfos[j].shapes.ItemAtFast(k); + PathSourceShape* shape = (PathSourceShape*)fInfos[j].shapes.ItemAtFast(k); shape->Paths()->RemovePath(fInfos[j].path); } } @@ -116,7 +118,7 @@ RemovePathsCommand::Undo() } int32 shapeCount = fInfos[i].shapes.CountItems(); for (int32 j = 0; j < shapeCount; j++) { - Shape* shape = (Shape*)fInfos[i].shapes.ItemAtFast(j); + PathSourceShape* shape = (PathSourceShape*)fInfos[i].shapes.ItemAtFast(j); shape->Paths()->AddPath(fInfos[i].path); } } diff --git a/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.cpp b/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.cpp index 299fd853dc..654625a6be 100644 --- a/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.cpp +++ b/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.cpp @@ -12,7 +12,7 @@ #include #include "PathContainer.h" -#include "Shape.h" +#include "PathSourceShape.h" #include "VectorPath.h" @@ -21,7 +21,7 @@ // constructor -UnassignPathCommand::UnassignPathCommand(Shape* shape, +UnassignPathCommand::UnassignPathCommand(PathSourceShape* shape, VectorPath* path) : Command(), fShape(shape), diff --git a/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.h b/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.h index 7395268611..bea72717a4 100644 --- a/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.h +++ b/src/apps/icon-o-matic/shape/commands/UnassignPathCommand.h @@ -14,7 +14,7 @@ _BEGIN_ICON_NAMESPACE - class Shape; + class PathSourceShape; class VectorPath; _END_ICON_NAMESPACE @@ -23,7 +23,7 @@ _USING_ICON_NAMESPACE class UnassignPathCommand : public Command { public: - UnassignPathCommand(Shape* shape, + UnassignPathCommand(PathSourceShape* shape, VectorPath* path); virtual ~UnassignPathCommand(); @@ -35,7 +35,7 @@ class UnassignPathCommand : public Command { virtual void GetName(BString& name); private: - Shape* fShape; + PathSourceShape* fShape; VectorPath* fPath; bool fPathRemoved; }; diff --git a/src/apps/icon-o-matic/style/AssignStyleCommand.cpp b/src/apps/icon-o-matic/style/AssignStyleCommand.cpp index 90f2a928be..5bde36d4f0 100644 --- a/src/apps/icon-o-matic/style/AssignStyleCommand.cpp +++ b/src/apps/icon-o-matic/style/AssignStyleCommand.cpp @@ -11,6 +11,7 @@ #include #include +#include "PathSourceShape.h" #include "Shape.h" #include "Style.h" @@ -20,7 +21,7 @@ // constructor -AssignStyleCommand::AssignStyleCommand(Shape* shape, +AssignStyleCommand::AssignStyleCommand(PathSourceShape* shape, Style* style) : Command(), fShape(shape), diff --git a/src/apps/icon-o-matic/style/AssignStyleCommand.h b/src/apps/icon-o-matic/style/AssignStyleCommand.h index b50c9252c8..511f7549fb 100644 --- a/src/apps/icon-o-matic/style/AssignStyleCommand.h +++ b/src/apps/icon-o-matic/style/AssignStyleCommand.h @@ -16,7 +16,7 @@ _BEGIN_ICON_NAMESPACE - class Shape; + class PathSourceShape; class Style; _END_ICON_NAMESPACE @@ -25,7 +25,7 @@ _USING_ICON_NAMESPACE class AssignStyleCommand : public Command { public: - AssignStyleCommand(Shape* shape, + AssignStyleCommand(PathSourceShape* shape, Style* style); virtual ~AssignStyleCommand(); @@ -37,7 +37,7 @@ class AssignStyleCommand : public Command { virtual void GetName(BString& name); private: - Shape* fShape; + PathSourceShape* fShape; Style* fOldStyle; Style* fNewStyle; }; diff --git a/src/apps/icon-o-matic/style/RemoveStylesCommand.cpp b/src/apps/icon-o-matic/style/RemoveStylesCommand.cpp index b29020efad..32bce883a0 100644 --- a/src/apps/icon-o-matic/style/RemoveStylesCommand.cpp +++ b/src/apps/icon-o-matic/style/RemoveStylesCommand.cpp @@ -14,8 +14,8 @@ #include #include +#include "PathSourceShape.h" #include "StyleContainer.h" -#include "Shape.h" #include "Style.h" @@ -44,8 +44,9 @@ RemoveStylesCommand::RemoveStylesCommand(StyleContainer* container, if (styles[i]) { int32 listenerCount = styles[i]->CountObservers(); for (int32 j = 0; j < listenerCount; j++) { - Shape* shape = dynamic_cast(styles[i]->ObserverAtFast(j)); - if (shape) + PathSourceShape* shape + = dynamic_cast(styles[i]->ObserverAtFast(j)); + if (shape != NULL) fInfos[i].shapes.AddItem((void*)shape); } } @@ -88,7 +89,7 @@ RemoveStylesCommand::Perform() continue; int32 shapeCount = fInfos[i].shapes.CountItems(); for (int32 j = 0; j < shapeCount; j++) { - Shape* shape = (Shape*)fInfos[i].shapes.ItemAtFast(j); + PathSourceShape* shape = (PathSourceShape*)fInfos[i].shapes.ItemAtFast(j); shape->SetStyle(fContainer->StyleAt(0)); } } @@ -117,7 +118,7 @@ RemoveStylesCommand::Undo() for (int32 j = i - 1; j >= 0; j--) { int32 shapeCount = fInfos[j].shapes.CountItems(); for (int32 k = 0; k < shapeCount; k++) { - Shape* shape = (Shape*)fInfos[j].shapes.ItemAtFast(k); + PathSourceShape* shape = (PathSourceShape*)fInfos[j].shapes.ItemAtFast(k); shape->SetStyle(fContainer->StyleAt(0)); } } @@ -125,7 +126,7 @@ RemoveStylesCommand::Undo() } int32 shapeCount = fInfos[i].shapes.CountItems(); for (int32 j = 0; j < shapeCount; j++) { - Shape* shape = (Shape*)fInfos[i].shapes.ItemAtFast(j); + PathSourceShape* shape = (PathSourceShape*)fInfos[i].shapes.ItemAtFast(j); shape->SetStyle(fInfos[i].style); } } diff --git a/src/build/libbe/icon/Jamfile b/src/build/libbe/icon/Jamfile index 3bad50a19e..64abf38160 100644 --- a/src/build/libbe/icon/Jamfile +++ b/src/build/libbe/icon/Jamfile @@ -38,6 +38,8 @@ BuildPlatformMergeObjectPIC icon_kit.o : # shape PathContainer.cpp + PathSourceShape.cpp + ReferenceImage.cpp Shape.cpp ShapeContainer.cpp VectorPath.cpp diff --git a/src/build/libicon/Jamfile b/src/build/libicon/Jamfile index 76797b9108..2f7b2877ca 100644 --- a/src/build/libicon/Jamfile +++ b/src/build/libicon/Jamfile @@ -36,6 +36,8 @@ BuildPlatformStaticLibrary libicon_build.a : # shape PathContainer.cpp + PathSourceShape.cpp + ReferenceImage.cpp Shape.cpp ShapeContainer.cpp VectorPath.cpp diff --git a/src/libs/icon/Icon.cpp b/src/libs/icon/Icon.cpp index 0e841dfa00..4a98eed3ed 100644 --- a/src/libs/icon/Icon.cpp +++ b/src/libs/icon/Icon.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2006, Haiku. + * Copyright 2006, 2023, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus + * Zardshard */ #include "Icon.h" @@ -12,6 +13,8 @@ #include #include "PathContainer.h" +#include "PathSourceShape.h" +#include "ReferenceImage.h" #include "Shape.h" #include "Style.h" #include "StyleContainer.h" @@ -79,30 +82,37 @@ Icon::Icon(const Icon& other) int32 shapeCount = other.fShapes->CountShapes(); for (int32 i = 0; i < shapeCount; i++) { Shape* shape = other.fShapes->ShapeAtFast(i); - Shape* clone = new (nothrow) Shape(*shape); + Shape* clone = shape->Clone(); if (!clone || !fShapes->AddShape(clone)) { delete clone; return; } - // the cloned shape references styles and paths in - // the "other" icon, replace them with "local" styles - // and paths - int32 styleIndex = other.fStyles->IndexOf(shape->Style()); - clone->SetStyle(fStyles->StyleAt(styleIndex)); - clone->Paths()->MakeEmpty(); - pathCount = shape->Paths()->CountPaths(); - for (int32 j = 0; j < pathCount; j++) { - VectorPath* remote = shape->Paths()->PathAtFast(j); - int32 index = other.fPaths->IndexOf(remote); - VectorPath* local = fPaths->PathAt(index); - if (!local) { - printf("failed to match remote and " - "local paths while cloning icon\n"); - continue; - } - if (!clone->Paths()->AddPath(local)) { - return; + // PathSourceShapes require further handling + PathSourceShape* pathSourceShape = dynamic_cast(shape); + PathSourceShape* pathSourceShapeClone = dynamic_cast(clone); + if (pathSourceShape != NULL && pathSourceShapeClone != NULL) { + // the cloned shape references styles and paths in + // the "other" icon, replace them with "local" styles + // and paths + + int32 styleIndex = other.fStyles->IndexOf(pathSourceShape->Style()); + pathSourceShapeClone->SetStyle(fStyles->StyleAt(styleIndex)); + + pathSourceShapeClone->Paths()->MakeEmpty(); + pathCount = pathSourceShape->Paths()->CountPaths(); + for (int32 j = 0; j < pathCount; j++) { + VectorPath* remote = pathSourceShape->Paths()->PathAtFast(j); + int32 index = other.fPaths->IndexOf(remote); + VectorPath* local = fPaths->PathAt(index); + if (!local) { + printf("failed to match remote and " + "local paths while cloning icon\n"); + continue; + } + if (!pathSourceShapeClone->Paths()->AddPath(local)) { + return; + } } } } diff --git a/src/libs/icon/IconRenderer.cpp b/src/libs/icon/IconRenderer.cpp index 2b12cad1b1..81094a79b9 100644 --- a/src/libs/icon/IconRenderer.cpp +++ b/src/libs/icon/IconRenderer.cpp @@ -1,19 +1,23 @@ /* - * Copyright 2006-2007, Haiku. All rights reserved. + * Copyright 2006-2007, 2023, Haiku. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus + * Zardshard */ #include "IconRenderer.h" +#include #include #include #include #include +#include +#include #include #include @@ -33,12 +37,22 @@ class IconRenderer::StyleHandler { }; public: +#ifdef ICON_O_MATIC + StyleHandler(::GammaTable& gammaTable, bool showReferences) + : fStyles(20), + fGammaTable(gammaTable), + fShowReferences(showReferences), + fTransparent(0, 0, 0, 0), + fColor(0, 0, 0, 0) + {} +#else StyleHandler(::GammaTable& gammaTable) : fStyles(20), fGammaTable(gammaTable), fTransparent(0, 0, 0, 0), fColor(0, 0, 0, 0) {} +#endif // ICON_O_MATIC ~StyleHandler() { @@ -53,7 +67,15 @@ class IconRenderer::StyleHandler { if (!styleItem) return true; - return styleItem->style->Gradient() == NULL; + if (styleItem->style->Gradient()) + return false; + +#ifdef ICON_O_MATIC + if (styleItem->style->Bitmap() && fShowReferences) + return false; +#endif // ICON_O_MATIC + + return true; } const agg::rgba8& color(unsigned styleIndex); @@ -86,14 +108,21 @@ private: void _GenerateGradient(agg::rgba8* span, int x, int y, unsigned len, GradientFunction function, int32 start, int32 end, const agg::rgba8* gradientColors, Transformation& gradientTransform); +#ifdef ICON_O_MATIC + void _GenerateImage(agg::rgba8* span, int x, int y, + unsigned len, Style* style, Transformation& transform); +#endif BList fStyles; ::GammaTable& fGammaTable; +#ifdef ICON_O_MATIC + bool fShowReferences; +#endif agg::rgba8 fTransparent; agg::rgba8 fColor; }; -// color + const agg::rgba8& IconRenderer::StyleHandler::color(unsigned styleIndex) { @@ -103,6 +132,13 @@ IconRenderer::StyleHandler::color(unsigned styleIndex) return fTransparent; } +#ifdef ICON_O_MATIC + if (styleItem->style->Bitmap() && !fShowReferences) { + fColor = agg::rgba8(0,0,0,0); + return fColor; + } +#endif + const rgb_color& c = styleItem->style->Color(); fColor = agg::rgba8(fGammaTable.dir(c.red), fGammaTable.dir(c.green), fGammaTable.dir(c.blue), c.alpha); @@ -110,18 +146,30 @@ IconRenderer::StyleHandler::color(unsigned styleIndex) return fColor; } -// generate_span + void IconRenderer::StyleHandler::generate_span(agg::rgba8* span, int x, int y, unsigned len, unsigned styleIndex) { StyleItem* styleItem = (StyleItem*)fStyles.ItemAt(styleIndex); - if (!styleItem || !styleItem->style->Gradient()) { + if (!styleItem + || (!styleItem->style->Gradient() +#ifdef ICON_O_MATIC + && !styleItem->style->Bitmap() +#endif + )) { printf("no style/gradient at index: %u!\n", styleIndex); // TODO: memset() span? return; } +#ifdef ICON_O_MATIC + if (styleItem->style->Bitmap()) { + _GenerateImage(span, x, y, len, styleItem->style, styleItem->transformation); + return; + } +#endif // ICON_O_MATIC + Style* style = styleItem->style; Gradient* gradient = style->Gradient(); const agg::rgba8* colors = style->GammaCorrectedColors(fGammaTable); @@ -166,7 +214,7 @@ IconRenderer::StyleHandler::generate_span(agg::rgba8* span, int x, int y, } } -// _GenerateGradient + template void IconRenderer::StyleHandler::_GenerateGradient(agg::rgba8* span, int x, int y, @@ -189,8 +237,51 @@ IconRenderer::StyleHandler::_GenerateGradient(agg::rgba8* span, int x, int y, gradientGenerator.generate(span, x, y, len); } + +#ifdef ICON_O_MATIC +void +IconRenderer::StyleHandler::_GenerateImage(agg::rgba8* span, int x, int y, + unsigned len, Style* style, Transformation& transform) +{ + // bitmap + BBitmap* bbitmap = style->Bitmap(); + agg::rendering_buffer bitmap; + bitmap.attach(static_cast(bbitmap->Bits()), bbitmap->Bounds().Width() + 1, + bbitmap->Bounds().Height() + 1, bbitmap->BytesPerRow()); + + // pixel format attached to bitmap + PixelFormat pixf_img(bitmap); + + // image interpolator + typedef agg::span_interpolator_linear<> interpolator_type; + interpolator_type interpolator(transform); + + // image accessor attached to pixel format of bitmap + typedef agg::image_accessor_wrap source_type; + source_type source(pixf_img); + + // image filter (nearest neighbor) + typedef agg::span_image_filter_rgba_nn< + source_type, interpolator_type> span_gen_type; + span_gen_type spanGenerator(source, interpolator); + + // generate the requested span + spanGenerator.generate(span, x, y, len); + + // apply postprocessing + for (unsigned i = 0; i < len; i++) { + span[i].apply_gamma_dir(fGammaTable); + span[i].a = (uint8) ((float) span[i].a * style->Alpha() / 255); + span[i].premultiply(); + } +} +#endif // ICON_O_MATIC + + // #pragma mark - + class HintingTransformer { public: @@ -204,7 +295,7 @@ class HintingTransformer { // #pragma mark - -// constructor + IconRenderer::IconRenderer(BBitmap* bitmap) : fBitmap(bitmap), fBackground(NULL), @@ -236,12 +327,12 @@ IconRenderer::IconRenderer(BBitmap* bitmap) bitmap->Bounds().IntegerHeight()); } -// destructor + IconRenderer::~IconRenderer() { } -// SetIcon + void IconRenderer::SetIcon(const Icon* icon) { @@ -252,21 +343,37 @@ IconRenderer::SetIcon(const Icon* icon) // TODO: ... ? } -// Render + void +#ifdef ICON_O_MATIC +IconRenderer::Render(bool showReferences) +#else IconRenderer::Render() +#endif { +#ifdef ICON_O_MATIC + _Render(fBitmap->Bounds(), showReferences); +#else _Render(fBitmap->Bounds()); +#endif } -// Render + void +#ifdef ICON_O_MATIC +IconRenderer::Render(const BRect& area, bool showReferences) +#else IconRenderer::Render(const BRect& area) +#endif { +#ifdef ICON_O_MATIC + _Render(fBitmap->Bounds() & area, showReferences); +#else _Render(fBitmap->Bounds() & area); +#endif } -//SetScale + void IconRenderer::SetScale(double scale) { @@ -274,14 +381,14 @@ IconRenderer::SetScale(double scale) fGlobalTransform.multiply(agg::trans_affine_scaling(scale)); } -//SetBackground + void IconRenderer::SetBackground(const BBitmap* background) { fBackground = background; } -//SetBackground + void IconRenderer::SetBackground(const agg::rgba8& background) { @@ -291,7 +398,7 @@ IconRenderer::SetBackground(const agg::rgba8& background) fBackgroundColor.a = background.a; } -// Demultiply + void IconRenderer::Demultiply() { @@ -314,14 +421,20 @@ IconRenderer::Demultiply() } } + // #pragma mark - + typedef agg::conv_transform ScaledPath; typedef agg::conv_transform HintedPath; -// _Render + void +#ifdef ICON_O_MATIC +IconRenderer::_Render(const BRect& r, bool showReferences) +#else IconRenderer::_Render(const BRect& r) +#endif { if (!fIcon) return; @@ -336,7 +449,11 @@ IconRenderer::_Render(const BRect& r) fBaseRendererPre.clear(fBackgroundColor); //bigtime_t start = system_time(); +#ifdef ICON_O_MATIC + StyleHandler styleHandler(fGammaTable, showReferences); +#else StyleHandler styleHandler(fGammaTable); +#endif fRasterizer.reset(); // iterate over the shapes in the icon, @@ -347,12 +464,7 @@ IconRenderer::_Render(const BRect& r) for (int32 i = 0; i < shapeCount; i++) { Shape* shape = fIcon->Shapes()->ShapeAtFast(i); - // Don't render shape if the Level Of Detail falls out of range. - // That's unless the scale is bigger than the maximum - // MaxVisibilityScale of 4.0f. - if (fGlobalTransform.scale() < shape->MinVisibilityScale() - || (fGlobalTransform.scale() > shape->MaxVisibilityScale() - && shape->MaxVisibilityScale() < 4.0f)) { + if (!shape->Visible(fGlobalTransform.scale())) { continue; } @@ -385,7 +497,12 @@ IconRenderer::_Render(const BRect& r) // if this is not the first shape, and the style contains // transparency, commit a render pass of previous shapes - if (i > 0 && style->HasTransparency()) + if (i > 0 + && (style->HasTransparency() +#ifdef ICON_O_MATIC + || style->Bitmap() != NULL +#endif + )) _CommitRenderPass(styleHandler); fRasterizer.styles(styleIndex, -1); @@ -413,7 +530,7 @@ IconRenderer::_Render(const BRect& r) //printf("rendering 64x64: %lld\n", system_time() - start); } -// _CommitRenderPass + void IconRenderer::_CommitRenderPass(StyleHandler& styleHandler, bool reset) { @@ -424,6 +541,3 @@ IconRenderer::_CommitRenderPass(StyleHandler& styleHandler, bool reset) fRasterizer.reset(); } - - - diff --git a/src/libs/icon/IconRenderer.h b/src/libs/icon/IconRenderer.h index d4c42681c0..b9422e4ace 100644 --- a/src/libs/icon/IconRenderer.h +++ b/src/libs/icon/IconRenderer.h @@ -1,9 +1,10 @@ /* - * Copyright 2006-2007, Haiku. + * Copyright 2006-2007, 2023, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus + * Zardshard */ #ifndef ICON_RENDERER_H #define ICON_RENDERER_H @@ -55,8 +56,13 @@ class IconRenderer { void SetIcon(const Icon* icon); +#ifdef ICON_O_MATIC + void Render(bool showReferences); + void Render(const BRect& area, bool showReferences); +#else void Render(); void Render(const BRect& area); +#endif // ICON_O_MATIC void SetScale(double scale); void SetBackground(const BBitmap* background); @@ -77,7 +83,11 @@ class IconRenderer { private: class StyleHandler; +#ifdef ICON_O_MATIC + void _Render(const BRect& area, bool showReferences); +#else void _Render(const BRect& area); +#endif // ICON_O_MATIC void _CommitRenderPass(StyleHandler& styleHandler, bool reset = true); diff --git a/src/libs/icon/Jamfile b/src/libs/icon/Jamfile index a27db9ebd6..237c9349f5 100644 --- a/src/libs/icon/Jamfile +++ b/src/libs/icon/Jamfile @@ -45,6 +45,8 @@ for architectureObject in [ MultiArchSubDirSetup ] { # shape PathContainer.cpp + PathSourceShape.cpp + ReferenceImage.cpp Shape.cpp ShapeContainer.cpp VectorPath.cpp diff --git a/src/libs/icon/flat_icon/FlatIconImporter.cpp b/src/libs/icon/flat_icon/FlatIconImporter.cpp index 6a1ff336a0..6e81a2a6fb 100644 --- a/src/libs/icon/flat_icon/FlatIconImporter.cpp +++ b/src/libs/icon/flat_icon/FlatIconImporter.cpp @@ -24,6 +24,7 @@ #include "LittleEndianBuffer.h" #include "PathCommandQueue.h" #include "PathContainer.h" +#include "PathSourceShape.h" #include "PerspectiveTransformer.h" #include "Shape.h" #include "StrokeTransformer.h" @@ -543,7 +544,7 @@ FlatIconImporter::_ReadPathSourceShape(LittleEndianBuffer& buffer, } // create the shape - Shape* shape = new (nothrow) Shape(style); + PathSourceShape* shape = new (nothrow) PathSourceShape(style); ObjectDeleter shapeDeleter(shape); if (!shape || shape->InitCheck() < B_OK) diff --git a/src/libs/icon/message/MessageImporter.cpp b/src/libs/icon/message/MessageImporter.cpp index bcf782122e..8cb306a0c0 100644 --- a/src/libs/icon/message/MessageImporter.cpp +++ b/src/libs/icon/message/MessageImporter.cpp @@ -1,9 +1,10 @@ /* - * Copyright 2006-2010, Haiku. All rights reserved. + * Copyright 2006-2010, 2023, Haiku. All rights reserved. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus + * Zardshard */ @@ -13,6 +14,9 @@ #include #include +#ifdef ICON_O_MATIC +#include +#endif #include #include #include @@ -20,6 +24,10 @@ #include "Defines.h" #include "Icon.h" #include "PathContainer.h" +#include "PathSourceShape.h" +#ifdef ICON_O_MATIC +#include "ReferenceImage.h" +#endif #include "Shape.h" #include "Style.h" #include "StyleContainer.h" @@ -178,56 +186,72 @@ MessageImporter::_ImportShapes(const BMessage* archive, PathContainer* paths, BMessage shapeArchive; for (int32 i = 0; allShapes.FindMessage("shape", i, &shapeArchive) == B_OK; i++) { - // find the right style - int32 styleIndex; - if (shapeArchive.FindInt32("style ref", &styleIndex) < B_OK) { - printf("MessageImporter::_ImportShapes() - " - "Shape %" B_PRId32 " doesn't reference a Style!", i); - continue; - } -#ifdef ICON_O_MATIC - Style* style = styles->StyleAt(StyleIndexFor(styleIndex)); -#else - Style* style = styles->StyleAt(styleIndex); -#endif - if (!style) { - printf("MessageImporter::_ImportShapes() - " - "Shape %" B_PRId32 " wants Style %" B_PRId32 ", which does not exist\n", - i, styleIndex); - continue; - } + int32 type; + status_t typeFound = shapeArchive.FindInt32("type", &type); + if (typeFound != B_OK || type == PathSourceShape::archive_code) { + // Type not being found shows an older format that did not support + // reference images - // create shape - Shape* shape = new (nothrow) Shape(style); - if (!shape || shape->InitCheck() < B_OK || !shapes->AddShape(shape)) { - delete shape; - ret = B_NO_MEMORY; - } - if (ret < B_OK) - break; - - // find the referenced paths - int32 pathIndex; - for (int32 j = 0; - shapeArchive.FindInt32("path ref", j, &pathIndex) == B_OK; - j++) { -#ifdef ICON_O_MATIC - VectorPath* path = paths->PathAt(PathIndexFor(pathIndex)); -#else - VectorPath* path = paths->PathAt(pathIndex); -#endif - if (!path) { + // find the right style + int32 styleIndex; + if (shapeArchive.FindInt32("style ref", &styleIndex) < B_OK) { printf("MessageImporter::_ImportShapes() - " - "Shape %" B_PRId32 " referenced path %" B_PRId32 ", " - "which does not exist\n", i, pathIndex); + "Shape %" B_PRId32 " doesn't reference a Style!", i); + continue; + } + #ifdef ICON_O_MATIC + Style* style = styles->StyleAt(StyleIndexFor(styleIndex)); + #else + Style* style = styles->StyleAt(styleIndex); + #endif + if (style == NULL) { + printf("MessageImporter::_ImportShapes() - " + "Shape %" B_PRId32 " wants Style %" B_PRId32 ", which does not exist\n", + i, styleIndex); continue; } - shape->Paths()->AddPath(path); - } - // Shape properties - if (ret == B_OK) - shape->Unarchive(&shapeArchive); + // create shape + PathSourceShape* shape = new (nothrow) PathSourceShape(style); + if (shape == NULL || shape->InitCheck() < B_OK || !shapes->AddShape(shape)) { + delete shape; + ret = B_NO_MEMORY; + } + if (ret < B_OK) + break; + + // find the referenced paths + int32 pathIndex; + for (int32 j = 0; + shapeArchive.FindInt32("path ref", j, &pathIndex) == B_OK; + j++) { + #ifdef ICON_O_MATIC + VectorPath* path = paths->PathAt(PathIndexFor(pathIndex)); + #else + VectorPath* path = paths->PathAt(pathIndex); + #endif + if (path == NULL) { + printf("MessageImporter::_ImportShapes() - " + "Shape %" B_PRId32 " referenced path %" B_PRId32 ", " + "which does not exist\n", i, pathIndex); + continue; + } + shape->Paths()->AddPath(path); + } + + // Shape properties + if (ret == B_OK) + shape->Unarchive(&shapeArchive); + } + #ifdef ICON_O_MATIC + else if (type == ReferenceImage::archive_code) { + ReferenceImage* shape = new (nothrow) ReferenceImage(&shapeArchive); + if (shape == NULL || shape->InitCheck() < B_OK || !shapes->AddShape(shape)) { + delete shape; + ret = B_NO_MEMORY; + } + } + #endif // ICON_O_MATIC } return ret; diff --git a/src/libs/icon/shape/PathSourceShape.cpp b/src/libs/icon/shape/PathSourceShape.cpp new file mode 100644 index 0000000000..a9bc84d408 --- /dev/null +++ b/src/libs/icon/shape/PathSourceShape.cpp @@ -0,0 +1,177 @@ +/* + * Copyright 2006, 2023, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + * Zardshard + */ + +#include "PathSourceShape.h" + +#include + +#include +#include + +#ifdef ICON_O_MATIC +# include "CommonPropertyIDs.h" +# include "Property.h" +# include "PropertyObject.h" +#endif // ICON_O_MATIC +#include "Style.h" + +using std::nothrow; + + +PathSourceShape::PathSourceShape(::Style* style) + : Shape(style), + + fMinVisibilityScale(0.0), + fMaxVisibilityScale(4.0) +{ +} + + +PathSourceShape::PathSourceShape(const PathSourceShape& other) + : Shape(other), + + fMinVisibilityScale(other.fMinVisibilityScale), + fMaxVisibilityScale(other.fMaxVisibilityScale) +{ +} + + +PathSourceShape::~PathSourceShape() +{ +} + + +// #pragma mark - + + +status_t +PathSourceShape::Unarchive(BMessage* archive) +{ + Shape::Unarchive(archive); + + // min visibility scale + if (archive->FindFloat("min visibility scale", &fMinVisibilityScale) < B_OK) + fMinVisibilityScale = 0.0; + + // max visibility scale + if (archive->FindFloat("max visibility scale", &fMaxVisibilityScale) < B_OK) + fMaxVisibilityScale = 4.0; + + if (fMinVisibilityScale < 0.0) + fMinVisibilityScale = 0.0; + if (fMinVisibilityScale > 4.0) + fMinVisibilityScale = 4.0; + if (fMaxVisibilityScale < 0.0) + fMaxVisibilityScale = 0.0; + if (fMaxVisibilityScale > 4.0) + fMaxVisibilityScale = 4.0; + + return B_OK; +} + + +#ifdef ICON_O_MATIC +status_t +PathSourceShape::Archive(BMessage* into, bool deep) const +{ + status_t ret = Shape::Archive(into, deep); + + // min visibility scale + if (ret == B_OK) + ret = into->AddFloat("min visibility scale", fMinVisibilityScale); + + // max visibility scale + if (ret == B_OK) + ret = into->AddFloat("max visibility scale", fMaxVisibilityScale); + + return ret; +} + + +PropertyObject* +PathSourceShape::MakePropertyObject() const +{ + PropertyObject* object = Shape::MakePropertyObject(); + if (object == NULL) + return NULL; + +// object->AddProperty(new BoolProperty(PROPERTY_HINTING, fHinting)); + + object->AddProperty(new FloatProperty(PROPERTY_MIN_VISIBILITY_SCALE, + fMinVisibilityScale, 0, 4)); + + object->AddProperty(new FloatProperty(PROPERTY_MAX_VISIBILITY_SCALE, + fMaxVisibilityScale, 0, 4)); + + return object; +} + + +bool +PathSourceShape::SetToPropertyObject(const PropertyObject* object) +{ + AutoNotificationSuspender _(this); + Shape::SetToPropertyObject(object); + + // hinting +// SetHinting(object->Value(PROPERTY_HINTING, fHinting)); + + // min visibility scale + SetMinVisibilityScale(object->Value(PROPERTY_MIN_VISIBILITY_SCALE, fMinVisibilityScale)); + + // max visibility scale + SetMaxVisibilityScale(object->Value(PROPERTY_MAX_VISIBILITY_SCALE, fMaxVisibilityScale)); + + return HasPendingNotifications(); +} +#endif // ICON_O_MATIC + + +// #pragma mark - + + +status_t +PathSourceShape::InitCheck() const +{ + return Shape::InitCheck(); +} + + +// #pragma mark - + + +void +PathSourceShape::SetMinVisibilityScale(float scale) +{ + if (fMinVisibilityScale == scale) + return; + + fMinVisibilityScale = scale; + Notify(); +} + + +void +PathSourceShape::SetMaxVisibilityScale(float scale) +{ + if (fMaxVisibilityScale == scale) + return; + + fMaxVisibilityScale = scale; + Notify(); +} + + +bool +PathSourceShape::Visible(float scale) const +{ + return scale >= MinVisibilityScale() + && (scale <= MaxVisibilityScale() || MaxVisibilityScale() >= 4.0f); +} + diff --git a/src/libs/icon/shape/PathSourceShape.h b/src/libs/icon/shape/PathSourceShape.h new file mode 100644 index 0000000000..cbb354aa7d --- /dev/null +++ b/src/libs/icon/shape/PathSourceShape.h @@ -0,0 +1,79 @@ +/* + * Copyright 2006-2007, 2023, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + * Zardshard + */ +#ifndef PATH_SOURCE_SHAPE_H +#define PATH_SOURCE_SHAPE_H + + +#include "IconBuild.h" +#include "Shape.h" + + +class BMessage; + + +_BEGIN_ICON_NAMESPACE + + +class PathContainer; +class PropertyObject; +class Style; + + +class PathSourceShape : public _ICON_NAMESPACE Shape { + public: + enum { + archive_code = 'shps' + }; + + PathSourceShape(::Style* style); + PathSourceShape(const PathSourceShape& other); + virtual ~PathSourceShape(); + + // IconObject interface + virtual status_t Unarchive(BMessage* archive); +#ifdef ICON_O_MATIC + virtual status_t Archive(BMessage* into, + bool deep = true) const; + + virtual PropertyObject* MakePropertyObject() const; + virtual bool SetToPropertyObject( + const PropertyObject* object); +#else + inline void Notify() {} +#endif // ICON_O_MATIC + + // PathSourceShape + virtual status_t InitCheck() const; + virtual PathSourceShape* Clone() const + { return new PathSourceShape(*this); } + + void SetStyle(::Style* style) + { Shape::SetStyle(style); } + inline ::Style* Style() const + { return Shape::Style(); } + + void SetMinVisibilityScale(float scale); + float MinVisibilityScale() const + { return fMinVisibilityScale; } + void SetMaxVisibilityScale(float scale); + float MaxVisibilityScale() const + { return fMaxVisibilityScale; } + + virtual bool Visible(float scale) const; + + private: + float fMinVisibilityScale; + float fMaxVisibilityScale; +}; + + +_END_ICON_NAMESPACE + + +#endif // PATH_SOURCE_SHAPE_H diff --git a/src/libs/icon/shape/ReferenceImage.cpp b/src/libs/icon/shape/ReferenceImage.cpp new file mode 100644 index 0000000000..96448276bc --- /dev/null +++ b/src/libs/icon/shape/ReferenceImage.cpp @@ -0,0 +1,210 @@ +/* + * Copyright 2006, 2023, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + * Zardshard + */ + +#ifdef ICON_O_MATIC +#include "ReferenceImage.h" + +#include +#include + +#include +#include + +#include "CommonPropertyIDs.h" +#include "Property.h" +#include "PropertyObject.h" +#include "Style.h" + +using std::nothrow; + + +ReferenceImage::ReferenceImage(BBitmap* image) + : Shape(new (nothrow) _ICON_NAMESPACE Style()), + fPath(NULL) +{ + if (Style() == NULL) + return; + Style()->ReleaseReference(); + // The shape constructor acquired a reference + + SetName(""); + SetImage(image); + + double width = (int) Style()->Bitmap()->Bounds().Width() + 1; + double height = (int) Style()->Bitmap()->Bounds().Height() + 1; + + // Scale to fill canvas + double longerSide = std::max(width, height); + ScaleBy(BPoint(0, 0), 64/longerSide, 64/longerSide); + + // Center + Transform(&width, &height); + TranslateBy(BPoint((64-width)/2, (64-height)/2)); +} + + +ReferenceImage::ReferenceImage(const ReferenceImage& other) + : Shape(new (nothrow) _ICON_NAMESPACE Style()), + fPath(NULL) +{ + if (Style() == NULL) + return; + Style()->ReleaseReference(); + // The shape constructor acquired a reference + + BBitmap* bitmap = new (nothrow) BBitmap(other.Style()->Bitmap()); + if (bitmap == NULL) + return; + + SetName(other.Name()); + SetImage(bitmap); + SetTransform(other); +} + + +ReferenceImage::ReferenceImage(BMessage* archive) + : Shape(new (nothrow) _ICON_NAMESPACE Style()), + fPath(NULL) +{ + Unarchive(archive); +} + + +ReferenceImage::~ReferenceImage() +{ +} + + +// #pragma mark - + + +status_t +ReferenceImage::Unarchive(BMessage* archive) +{ + // IconObject properties + status_t ret = IconObject::Unarchive(archive); + if (ret < B_OK) + return ret; + + // read transformation + const double* matrix; + ssize_t dataSize; + ret = archive->FindData("transformation", B_DOUBLE_TYPE, + (const void**) &matrix, &dataSize); + if (ret < B_OK) + return ret; + if (dataSize != Transformable::matrix_size * sizeof(double)) + return B_BAD_VALUE; + LoadFrom(matrix); + + BBitmap* bitmap = dynamic_cast(BBitmap::Instantiate(archive)); + if (bitmap == NULL) + return B_ERROR; + SetImage(bitmap); + + return B_OK; +} + + +status_t +ReferenceImage::Archive(BMessage* into, bool deep) const +{ + status_t ret = IconObject::Archive(into, deep); + if (ret < B_OK) + return ret; + + // transformation + int32 size = Transformable::matrix_size; + double matrix[size]; + StoreTo(matrix); + ret = into->AddData("transformation", B_DOUBLE_TYPE, + matrix, size * sizeof(double)); + if (ret < B_OK) + return ret; + + // image + ret = Style()->Bitmap()->Archive(into, deep); + return ret; +} + + +PropertyObject* +ReferenceImage::MakePropertyObject() const +{ + PropertyObject* object = IconObject::MakePropertyObject(); + + object->AddProperty(new IntProperty(PROPERTY_ALPHA, Style()->Alpha(), 0, 255)); + + return object; +} + + +bool +ReferenceImage::SetToPropertyObject(const PropertyObject* object) +{ + AutoNotificationSuspender _(this); + IconObject::SetToPropertyObject(object); + + Style()->SetAlpha(object->Value(PROPERTY_ALPHA, (int32) Style()->Alpha())); + + return HasPendingNotifications(); +} + + +// #pragma mark - + + +status_t +ReferenceImage::InitCheck() const +{ + status_t status = Shape::InitCheck(); + if (status != B_OK) + return status; + + if (Style() == NULL || Style()->Bitmap() == NULL) + return B_NO_MEMORY; + + return B_OK; +} + + +// #pragma mark - + + +void +ReferenceImage::SetImage(BBitmap* image) +{ + if (fPath != NULL) { + Paths()->MakeEmpty(); + delete fPath; + fPath = NULL; + } + + if (image != NULL) { + // Update style + Style()->SetBitmap(image); + + // Update shape + fPath = new (nothrow) VectorPath(); + if (fPath == NULL) + return; + + double width = (int) Style()->Bitmap()->Bounds().Width() + 1; + double height = (int) Style()->Bitmap()->Bounds().Height() + 1; + fPath->AddPoint(BPoint(0, 0)); + fPath->AddPoint(BPoint(0, height)); + fPath->AddPoint(BPoint(width, height)); + fPath->AddPoint(BPoint(width, 0)); + fPath->SetClosed(true); + Paths()->AddPath(fPath); + } +} + +#endif // ICON_O_MATIC + diff --git a/src/libs/icon/shape/ReferenceImage.h b/src/libs/icon/shape/ReferenceImage.h new file mode 100644 index 0000000000..00d67a4bd6 --- /dev/null +++ b/src/libs/icon/shape/ReferenceImage.h @@ -0,0 +1,71 @@ +/* + * Copyright 2006-2007, 2023, Haiku. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Stephan Aßmus + * Zardshard + */ +#ifndef REFERENCE_IMAGE_H +#define REFERENCE_IMAGE_H + +#ifdef ICON_O_MATIC + +#include "IconObject.h" +#include "Observer.h" +#include "IconBuild.h" +#include "PathContainer.h" +#include "PathSource.h" +#include "Shape.h" +#include "Transformable.h" +#include "VectorPath.h" + +#include +#include + + +_BEGIN_ICON_NAMESPACE + + +class Style; + +class ReferenceImage : public _ICON_NAMESPACE Shape { + public: + enum { + archive_code = 'shri' + }; + + ReferenceImage(BBitmap* image); + // transfers ownership of image + ReferenceImage(const ReferenceImage& other); + ReferenceImage(BMessage* archive); + virtual ~ReferenceImage(); + + // IconObject interface + virtual status_t Unarchive(BMessage* archive); + virtual status_t Archive(BMessage* into, + bool deep = true) const; + + virtual PropertyObject* MakePropertyObject() const; + virtual bool SetToPropertyObject( + const PropertyObject* object); + // Shape + virtual status_t InitCheck() const; + virtual Shape* Clone() const + { return new ReferenceImage(*this); } + + virtual void SetImage(BBitmap* image); + // transfers ownership of image + + virtual bool Visible(float scale) const + { return true; } + private: + VectorPath* fPath; +}; + + +_END_ICON_NAMESPACE + + +#endif // ICON_O_MATIC +#endif // REFERENCE_IMAGE_H diff --git a/src/libs/icon/shape/Shape.cpp b/src/libs/icon/shape/Shape.cpp index 3c4eaed60a..a9d76de341 100644 --- a/src/libs/icon/shape/Shape.cpp +++ b/src/libs/icon/shape/Shape.cpp @@ -27,21 +27,22 @@ using std::nothrow; + #ifdef ICON_O_MATIC -// constructor ShapeListener::ShapeListener() { } -// destructor + ShapeListener::~ShapeListener() { } #endif // ICON_O_MATIC + // #pragma mark - -// constructor + Shape::Shape(::Style* style) #ifdef ICON_O_MATIC : IconObject(""), @@ -61,9 +62,7 @@ Shape::Shape(::Style* style) fLastBounds(0, 0, -1, -1), - fHinting(false), - fMinVisibilityScale(0.0), - fMaxVisibilityScale(4.0) + fHinting(false) #ifdef ICON_O_MATIC , fListeners(8) @@ -77,7 +76,7 @@ Shape::Shape(::Style* style) #endif } -// constructor + Shape::Shape(const Shape& other) #ifdef ICON_O_MATIC : IconObject(other), @@ -97,9 +96,7 @@ Shape::Shape(const Shape& other) fLastBounds(0, 0, -1, -1), - fHinting(other.fHinting), - fMinVisibilityScale(other.fMinVisibilityScale), - fMaxVisibilityScale(other.fMaxVisibilityScale) + fHinting(false) #ifdef ICON_O_MATIC , fListeners(8) @@ -111,6 +108,7 @@ Shape::Shape(const Shape& other) #ifdef ICON_O_MATIC fPaths->AddListener(this); #endif + // copy the path references from // the other shape if (other.fPaths) { @@ -133,7 +131,7 @@ Shape::Shape(const Shape& other) } } -// destructor + Shape::~Shape() { int32 count = fTransformers.CountItems(); @@ -155,11 +153,12 @@ Shape::~Shape() SetStyle(NULL); } + // #pragma mark - -// Unarchive + status_t -Shape::Unarchive(const BMessage* archive) +Shape::Unarchive(BMessage* archive) { #ifdef ICON_O_MATIC // IconObject properties @@ -170,11 +169,15 @@ Shape::Unarchive(const BMessage* archive) status_t ret; #endif + // hinting + if (archive->FindBool("hinting", &fHinting) < B_OK) + fHinting = false; + // recreate transformers BMessage transformerArchive; for (int32 i = 0; archive->FindMessage("transformer", i, - &transformerArchive) == B_OK; + &transformerArchive) == B_OK; i++) { Transformer* transformer = TransformerFactory::TransformerFor( @@ -189,44 +192,24 @@ Shape::Unarchive(const BMessage* archive) const void* matrix; ssize_t dataSize = size * sizeof(double); ret = archive->FindData("transformation", B_DOUBLE_TYPE, - &matrix, &dataSize); + &matrix, &dataSize); if (ret == B_OK && dataSize == (ssize_t)(size * sizeof(double))) LoadFrom((const double*)matrix); - // hinting - if (archive->FindBool("hinting", &fHinting) < B_OK) - fHinting = false; - - // min visibility scale - if (archive->FindFloat("min visibility scale", - &fMinVisibilityScale) < B_OK) - fMinVisibilityScale = 0.0; - - // max visibility scale - if (archive->FindFloat("max visibility scale", - &fMaxVisibilityScale) < B_OK) - fMaxVisibilityScale = 4.0; - - if (fMinVisibilityScale < 0.0) - fMinVisibilityScale = 0.0; - if (fMinVisibilityScale > 4.0) - fMinVisibilityScale = 4.0; - if (fMaxVisibilityScale < 0.0) - fMaxVisibilityScale = 0.0; - if (fMaxVisibilityScale > 4.0) - fMaxVisibilityScale = 4.0; - return B_OK; } -#ifdef ICON_O_MATIC -// Archive +#ifdef ICON_O_MATIC status_t Shape::Archive(BMessage* into, bool deep) const { status_t ret = IconObject::Archive(into, deep); + // hinting + if (ret == B_OK) + ret = into->AddBool("hinting", fHinting); + // transformers if (ret == B_OK) { int32 count = CountTransformers(); @@ -247,69 +230,32 @@ Shape::Archive(BMessage* into, bool deep) const double matrix[size]; StoreTo(matrix); ret = into->AddData("transformation", B_DOUBLE_TYPE, - matrix, size * sizeof(double)); + matrix, size * sizeof(double)); } - // hinting - if (ret ==B_OK) - ret = into->AddBool("hinting", fHinting); - - // min visibility scale - if (ret ==B_OK) - ret = into->AddFloat("min visibility scale", - fMinVisibilityScale); - - // max visibility scale - if (ret ==B_OK) - ret = into->AddFloat("max visibility scale", - fMaxVisibilityScale); - return ret; } -// MakePropertyObject + PropertyObject* Shape::MakePropertyObject() const { PropertyObject* object = IconObject::MakePropertyObject(); - if (!object) - return NULL; - -// object->AddProperty(new BoolProperty(PROPERTY_HINTING, fHinting)); - - object->AddProperty(new FloatProperty(PROPERTY_MIN_VISIBILITY_SCALE, - fMinVisibilityScale, 0, 4)); - - object->AddProperty(new FloatProperty(PROPERTY_MAX_VISIBILITY_SCALE, - fMaxVisibilityScale, 0, 4)); - return object; } -// SetToPropertyObject + bool Shape::SetToPropertyObject(const PropertyObject* object) { - AutoNotificationSuspender _(this); IconObject::SetToPropertyObject(object); - - // hinting -// SetHinting(object->Value(PROPERTY_HINTING, fHinting)); - - // min visibility scale - SetMinVisibilityScale(object->Value(PROPERTY_MIN_VISIBILITY_SCALE, - fMinVisibilityScale)); - - // max visibility scale - SetMaxVisibilityScale(object->Value(PROPERTY_MAX_VISIBILITY_SCALE, - fMaxVisibilityScale)); - - return HasPendingNotifications(); + return true; } + // #pragma mark - -// TransformationChanged + void Shape::TransformationChanged() { @@ -317,9 +263,10 @@ Shape::TransformationChanged() _NotifyRerender(); } + // #pragma mark - -// ObjectChanged + void Shape::ObjectChanged(const Observable* object) { @@ -329,9 +276,10 @@ Shape::ObjectChanged(const Observable* object) _NotifyRerender(); } + // #pragma mark - -// PathAdded + void Shape::PathAdded(VectorPath* path, int32 index) { @@ -340,7 +288,7 @@ Shape::PathAdded(VectorPath* path, int32 index) _NotifyRerender(); } -// PathRemoved + void Shape::PathRemoved(VectorPath* path) { @@ -349,65 +297,66 @@ Shape::PathRemoved(VectorPath* path) path->ReleaseReference(); } + // #pragma mark - -// PointAdded + void Shape::PointAdded(int32 index) { _NotifyRerender(); } -// PointRemoved + void Shape::PointRemoved(int32 index) { _NotifyRerender(); } -// PointChanged + void Shape::PointChanged(int32 index) { _NotifyRerender(); } -// PathChanged + void Shape::PathChanged() { _NotifyRerender(); } -// PathClosedChanged + void Shape::PathClosedChanged() { _NotifyRerender(); } -// PathReversed + void Shape::PathReversed() { _NotifyRerender(); } - #endif // ICON_O_MATIC // #pragma mark - -// InitCheck + status_t Shape::InitCheck() const { return fPaths ? B_OK : B_NO_MEMORY; } + // #pragma mark - -// SetStyle + void Shape::SetStyle(::Style* style) { @@ -434,9 +383,10 @@ Shape::SetStyle(::Style* style) #endif } + // #pragma mark - -// Bounds + BRect Shape::Bounds(bool updateLast) const { @@ -452,9 +402,9 @@ Shape::Bounds(bool updateLast) const ::VertexSource& source = const_cast(this)->VertexSource(); agg::conv_transform< ::VertexSource, Transformable> - transformedSource(source, *this); + transformedSource(source, *this); agg::bounding_rect(transformedSource, pathID, 0, 1, - &left, &top, &right, &bottom); + &left, &top, &right, &bottom); BRect bounds(left, top, right, bottom); @@ -464,7 +414,7 @@ Shape::Bounds(bool updateLast) const return bounds; } -// VertexSource + ::VertexSource& Shape::VertexSource() { @@ -479,28 +429,28 @@ Shape::VertexSource() if (fNeedsUpdate) { fPathSource.Update(source->WantsOpenPaths(), - source->ApproximationScale()); + source->ApproximationScale()); fNeedsUpdate = false; } return *source; } -// SetGlobalScale + void Shape::SetGlobalScale(double scale) { fPathSource.SetGlobalScale(scale); } -// AddTransformer + bool Shape::AddTransformer(Transformer* transformer) { return AddTransformer(transformer, CountTransformers()); } -// AddTransformer + bool Shape::AddTransformer(Transformer* transformer, int32 index) { @@ -520,7 +470,7 @@ Shape::AddTransformer(Transformer* transformer, int32 index) return true; } -// RemoveTransformer + bool Shape::RemoveTransformer(Transformer* transformer) { @@ -538,83 +488,49 @@ Shape::RemoveTransformer(Transformer* transformer) return false; } + // #pragma mark - -// CountShapes + int32 Shape::CountTransformers() const { return fTransformers.CountItems(); } -// HasTransformer + bool Shape::HasTransformer(Transformer* transformer) const { return fTransformers.HasItem((void*)transformer); } -// IndexOf + int32 Shape::IndexOf(Transformer* transformer) const { return fTransformers.IndexOf((void*)transformer); } -// TransformerAt + Transformer* Shape::TransformerAt(int32 index) const { return (Transformer*)fTransformers.ItemAt(index); } -// TransformerAtFast + Transformer* Shape::TransformerAtFast(int32 index) const { return (Transformer*)fTransformers.ItemAtFast(index); } -// #pragma mark - - -// SetHinting -void -Shape::SetHinting(bool hinting) -{ - if (fHinting == hinting) - return; - - fHinting = hinting; - Notify(); -} - -// SetMinVisibilityScale -void -Shape::SetMinVisibilityScale(float scale) -{ - if (fMinVisibilityScale == scale) - return; - - fMinVisibilityScale = scale; - Notify(); -} - -// SetMaxVisibilityScale -void -Shape::SetMaxVisibilityScale(float scale) -{ - if (fMaxVisibilityScale == scale) - return; - - fMaxVisibilityScale = scale; - Notify(); -} // #pragma mark - + #ifdef ICON_O_MATIC - -// AddListener bool Shape::AddListener(ShapeListener* listener) { @@ -623,16 +539,17 @@ Shape::AddListener(ShapeListener* listener) return false; } -// RemoveListener + bool Shape::RemoveListener(ShapeListener* listener) { return fListeners.RemoveItem((void*)listener); } + // #pragma mark - -// _NotifyTransformerAdded + void Shape::_NotifyTransformerAdded(Transformer* transformer, int32 index) const { @@ -647,7 +564,7 @@ Shape::_NotifyTransformerAdded(Transformer* transformer, int32 index) const _NotifyRerender(); } -// _NotifyTransformerRemoved + void Shape::_NotifyTransformerRemoved(Transformer* transformer) const { @@ -662,7 +579,7 @@ Shape::_NotifyTransformerRemoved(Transformer* transformer) const _NotifyRerender(); } -// _NotifyStyleChanged + void Shape::_NotifyStyleChanged(::Style* oldStyle, ::Style* newStyle) const { @@ -677,13 +594,23 @@ Shape::_NotifyStyleChanged(::Style* oldStyle, ::Style* newStyle) const _NotifyRerender(); } -// _NotifyRerender + void Shape::_NotifyRerender() const { fNeedsUpdate = true; Notify(); } - #endif // ICON_O_MATIC + +void +Shape::SetHinting(bool hinting) +{ + if (fHinting == hinting) + return; + + fHinting = hinting; + Notify(); +} + diff --git a/src/libs/icon/shape/Shape.h b/src/libs/icon/shape/Shape.h index 8f1e5b15f0..08e2d5cb8d 100644 --- a/src/libs/icon/shape/Shape.h +++ b/src/libs/icon/shape/Shape.h @@ -23,11 +23,13 @@ #include +class BMessage; + _BEGIN_ICON_NAMESPACE - class Style; + #ifdef ICON_O_MATIC // TODO: merge Observer and ShapeListener interface // ie add "AppearanceChanged(Shape* shape)" @@ -40,6 +42,7 @@ class ShapeListener { int32 index) = 0; virtual void TransformerRemoved(Transformer* t) = 0; + // TODO: this is not useful for all subclasses of Shape (e.g. ReferenceImage) virtual void StyleChanged(::Style* oldStyle, ::Style* newStyle) = 0; }; @@ -61,7 +64,7 @@ class Shape : public _ICON_NAMESPACE Transformable { virtual ~Shape(); // IconObject interface - virtual status_t Unarchive(const BMessage* archive); + virtual status_t Unarchive(BMessage* archive); #ifdef ICON_O_MATIC virtual status_t Archive(BMessage* into, bool deep = true) const; @@ -92,12 +95,13 @@ class Shape : public _ICON_NAMESPACE Transformable { #endif // ICON_O_MATIC // Shape - status_t InitCheck() const; + virtual status_t InitCheck() const; + virtual Shape* Clone() const = 0; inline PathContainer* Paths() const { return fPaths; } - void SetStyle(::Style* style); +public: inline ::Style* Style() const { return fStyle; } @@ -124,12 +128,8 @@ class Shape : public _ICON_NAMESPACE Transformable { void SetHinting(bool hinting); bool Hinting() const { return fHinting; } - void SetMinVisibilityScale(float scale); - float MinVisibilityScale() const - { return fMinVisibilityScale; } - void SetMaxVisibilityScale(float scale); - float MaxVisibilityScale() const - { return fMaxVisibilityScale; } + + virtual bool Visible(float scale) const = 0; #ifdef ICON_O_MATIC bool AddListener(ShapeListener* listener); @@ -146,6 +146,9 @@ class Shape : public _ICON_NAMESPACE Transformable { void _NotifyRerender() const; #endif // ICON_O_MATIC + protected: + void SetStyle(::Style* style); + private: PathContainer* fPaths; ::Style* fStyle; @@ -157,15 +160,12 @@ class Shape : public _ICON_NAMESPACE Transformable { mutable BRect fLastBounds; bool fHinting; - float fMinVisibilityScale; - float fMaxVisibilityScale; #ifdef ICON_O_MATIC BList fListeners; #endif }; - _END_ICON_NAMESPACE diff --git a/src/libs/icon/style/Style.cpp b/src/libs/icon/style/Style.cpp index 0e997f2218..85ededa385 100644 --- a/src/libs/icon/style/Style.cpp +++ b/src/libs/icon/style/Style.cpp @@ -1,16 +1,18 @@ /* - * Copyright 2006, Haiku. + * Copyright 2006, 2023, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus + * Zardshard */ #include "Style.h" #include -# include +#include +#include #ifdef ICON_O_MATIC # include "ui_defines.h" @@ -22,7 +24,7 @@ using std::nothrow; -// constructor + Style::Style() #ifdef ICON_O_MATIC : IconObject("