1 /* 2 * Copyright 2006, Haiku. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Stephan Aßmus <superstippi@gmx.de> 7 */ 8 9 #include "FreezeTransformationCommand.h" 10 11 #include <new> 12 #include <stdio.h> 13 #include <string.h> 14 15 #include <Catalog.h> 16 #include <Locale.h> 17 18 #include "GradientTransformable.h" 19 #include "Shape.h" 20 #include "Style.h" 21 #include "VectorPath.h" 22 23 24 #undef B_TRANSLATE_CONTEXT 25 #define B_TRANSLATE_CONTEXT "Icon-O-Matic-FreezeTransformationCmd" 26 27 28 using std::nothrow; 29 30 // constructor 31 FreezeTransformationCommand::FreezeTransformationCommand( 32 Shape** const shapes, 33 int32 count) 34 : Command(), 35 fShapes(shapes && count > 0 ? new (nothrow) Shape*[count] : NULL), 36 fOriginalTransformations(count > 0 ? new (nothrow) double[ 37 count * Transformable::matrix_size] 38 : NULL), 39 fCount(count) 40 { 41 if (!fShapes || !fOriginalTransformations) 42 return; 43 44 memcpy(fShapes, shapes, sizeof(Shape*) * fCount); 45 46 bool initOk = false; 47 48 for (int32 i = 0; i < fCount; i++) { 49 if (!fShapes[i]) 50 continue; 51 if (!fShapes[i]->IsIdentity()) 52 initOk = true; 53 fShapes[i]->StoreTo(&fOriginalTransformations[ 54 i * Transformable::matrix_size]); 55 } 56 57 if (!initOk) { 58 delete[] fShapes; 59 fShapes = NULL; 60 delete[] fOriginalTransformations; 61 fOriginalTransformations = NULL; 62 } 63 } 64 65 // destructor 66 FreezeTransformationCommand::~FreezeTransformationCommand() 67 { 68 delete[] fShapes; 69 delete[] fOriginalTransformations; 70 } 71 72 // InitCheck 73 status_t 74 FreezeTransformationCommand::InitCheck() 75 { 76 return fShapes && fOriginalTransformations ? B_OK : B_NO_INIT; 77 } 78 79 // Perform 80 status_t 81 FreezeTransformationCommand::Perform() 82 { 83 for (int32 i = 0; i < fCount; i++) { 84 if (!fShapes[i] || fShapes[i]->IsIdentity()) 85 continue; 86 87 _ApplyTransformation(fShapes[i], *(fShapes[i])); 88 fShapes[i]->Reset(); 89 } 90 91 return B_OK; 92 } 93 94 // Undo 95 status_t 96 FreezeTransformationCommand::Undo() 97 { 98 for (int32 i = 0; i < fCount; i++) { 99 if (!fShapes[i]) 100 continue; 101 102 // restore original transformation 103 fShapes[i]->LoadFrom(&fOriginalTransformations[ 104 i * Transformable::matrix_size]); 105 106 Transformable transform(*(fShapes[i])); 107 if (!transform.IsValid() || transform.IsIdentity()) 108 continue; 109 110 transform.Invert(); 111 _ApplyTransformation(fShapes[i], transform); 112 } 113 114 return B_OK; 115 } 116 117 // GetName 118 void 119 FreezeTransformationCommand::GetName(BString& name) 120 { 121 if (fCount > 1) 122 name << B_TRANSLATE("Freeze Shapes"); 123 else 124 name << B_TRANSLATE("Freeze Shape"); 125 } 126 127 // #pragma mark - 128 129 // _ApplyTransformation 130 void 131 FreezeTransformationCommand::_ApplyTransformation(Shape* shape, 132 const Transformable& transform) 133 { 134 // apply inverse of old shape transformation to every assigned path 135 int32 pathCount = shape->Paths()->CountPaths(); 136 for (int32 i = 0; i < pathCount; i++) { 137 VectorPath* path = shape->Paths()->PathAtFast(i); 138 int32 shapes = 0; 139 int32 listeners = path->CountListeners(); 140 for (int32 j = 0; j < listeners; j++) { 141 if (dynamic_cast<Shape*>(path->ListenerAtFast(j))) 142 shapes++; 143 } 144 // only freeze transformation of path if only one 145 // shape has it assigned 146 if (shapes == 1) { 147 path->ApplyTransform(transform); 148 } else { 149 printf("Not transfering transformation of \"%s\" onto " 150 "path \"%s\", because %ld other shapes " 151 "have it assigned.\n", shape->Name(), path->Name(), 152 shapes - 1); 153 } 154 } 155 // take care of style too 156 if (shape->Style() && shape->Style()->Gradient()) { 157 // TODO: not if more than one shape have this style assigned! 158 shape->Style()->Gradient()->Multiply(transform); 159 } 160 } 161