/* * Copyright 2006, Haiku. * Distributed under the terms of the MIT License. * * Authors: * Stephan Aßmus */ #include "FreezeTransformationCommand.h" #include #include #include #include #include #include "GradientTransformable.h" #include "Shape.h" #include "Style.h" #include "VectorPath.h" #undef B_TRANSLATION_CONTEXT #define B_TRANSLATION_CONTEXT "Icon-O-Matic-FreezeTransformationCmd" using std::nothrow; // constructor FreezeTransformationCommand::FreezeTransformationCommand( Shape** const shapes, int32 count) : Command(), fShapes(shapes && count > 0 ? new (nothrow) Shape*[count] : NULL), fOriginalTransformations(count > 0 ? new (nothrow) double[ count * Transformable::matrix_size] : NULL), fCount(count) { if (!fShapes || !fOriginalTransformations) return; memcpy(fShapes, shapes, sizeof(Shape*) * fCount); bool initOk = false; for (int32 i = 0; i < fCount; i++) { if (!fShapes[i]) continue; if (!fShapes[i]->IsIdentity()) initOk = true; fShapes[i]->StoreTo(&fOriginalTransformations[ i * Transformable::matrix_size]); } if (!initOk) { delete[] fShapes; fShapes = NULL; delete[] fOriginalTransformations; fOriginalTransformations = NULL; } } // destructor FreezeTransformationCommand::~FreezeTransformationCommand() { delete[] fShapes; delete[] fOriginalTransformations; } // InitCheck status_t FreezeTransformationCommand::InitCheck() { return fShapes && fOriginalTransformations ? B_OK : B_NO_INIT; } // Perform status_t FreezeTransformationCommand::Perform() { for (int32 i = 0; i < fCount; i++) { if (!fShapes[i] || fShapes[i]->IsIdentity()) continue; _ApplyTransformation(fShapes[i], *(fShapes[i])); fShapes[i]->Reset(); } return B_OK; } // Undo status_t FreezeTransformationCommand::Undo() { for (int32 i = 0; i < fCount; i++) { if (!fShapes[i]) continue; // restore original transformation fShapes[i]->LoadFrom(&fOriginalTransformations[ i * Transformable::matrix_size]); Transformable transform(*(fShapes[i])); if (!transform.IsValid() || transform.IsIdentity()) continue; transform.Invert(); _ApplyTransformation(fShapes[i], transform); } return B_OK; } // GetName void FreezeTransformationCommand::GetName(BString& name) { if (fCount > 1) name << B_TRANSLATE("Freeze Shapes"); else name << B_TRANSLATE("Freeze Shape"); } // #pragma mark - // _ApplyTransformation void FreezeTransformationCommand::_ApplyTransformation(Shape* shape, const Transformable& transform) { // apply inverse of old shape transformation to every assigned path int32 pathCount = shape->Paths()->CountPaths(); for (int32 i = 0; i < pathCount; i++) { VectorPath* path = shape->Paths()->PathAtFast(i); int32 shapes = 0; int32 listeners = path->CountListeners(); for (int32 j = 0; j < listeners; j++) { if (dynamic_cast(path->ListenerAtFast(j))) shapes++; } // only freeze transformation of path if only one // shape has it assigned if (shapes == 1) { path->ApplyTransform(transform); } else { printf("Not transfering transformation of \"%s\" onto " "path \"%s\", because %" B_PRId32 " other shapes " "have it assigned.\n", shape->Name(), path->Name(), shapes - 1); } } // take care of style too if (shape->Style() && shape->Style()->Gradient()) { // TODO: not if more than one shape have this style assigned! shape->Style()->Gradient()->Multiply(transform); } }