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 #include <StringFormat.h> 18 19 #include "GradientTransformable.h" 20 #include "PathSourceShape.h" 21 #include "Style.h" 22 #include "VectorPath.h" 23 24 25 #undef B_TRANSLATION_CONTEXT 26 #define B_TRANSLATION_CONTEXT "Icon-O-Matic-FreezeTransformationCmd" 27 28 29 using std::nothrow; 30 31 // constructor 32 FreezeTransformationCommand::FreezeTransformationCommand( 33 PathSourceShape** const shapes, 34 int32 count) 35 : Command(), 36 fShapes(shapes && count > 0 ? new (nothrow) PathSourceShape*[count] : NULL), 37 fOriginalTransformations(count > 0 ? new (nothrow) double[ 38 count * Transformable::matrix_size] 39 : NULL), 40 fCount(count) 41 { 42 if (!fShapes || !fOriginalTransformations) 43 return; 44 45 memcpy(fShapes, shapes, sizeof(PathSourceShape*) * fCount); 46 47 bool initOk = false; 48 49 for (int32 i = 0; i < fCount; i++) { 50 if (!fShapes[i]) 51 continue; 52 if (!fShapes[i]->IsIdentity()) 53 initOk = true; 54 fShapes[i]->StoreTo(&fOriginalTransformations[ 55 i * Transformable::matrix_size]); 56 } 57 58 if (!initOk) { 59 delete[] fShapes; 60 fShapes = NULL; 61 delete[] fOriginalTransformations; 62 fOriginalTransformations = NULL; 63 } 64 } 65 66 // destructor 67 FreezeTransformationCommand::~FreezeTransformationCommand() 68 { 69 delete[] fShapes; 70 delete[] fOriginalTransformations; 71 } 72 73 // InitCheck 74 status_t 75 FreezeTransformationCommand::InitCheck() 76 { 77 return fShapes && fOriginalTransformations ? B_OK : B_NO_INIT; 78 } 79 80 // Perform 81 status_t 82 FreezeTransformationCommand::Perform() 83 { 84 for (int32 i = 0; i < fCount; i++) { 85 if (!fShapes[i] || fShapes[i]->IsIdentity()) 86 continue; 87 88 _ApplyTransformation(fShapes[i], *(fShapes[i])); 89 fShapes[i]->Reset(); 90 } 91 92 return B_OK; 93 } 94 95 // Undo 96 status_t 97 FreezeTransformationCommand::Undo() 98 { 99 for (int32 i = 0; i < fCount; i++) { 100 if (!fShapes[i]) 101 continue; 102 103 // restore original transformation 104 fShapes[i]->LoadFrom(&fOriginalTransformations[ 105 i * Transformable::matrix_size]); 106 107 Transformable transform(*(fShapes[i])); 108 if (!transform.IsValid() || transform.IsIdentity()) 109 continue; 110 111 transform.Invert(); 112 _ApplyTransformation(fShapes[i], transform); 113 } 114 115 return B_OK; 116 } 117 118 // GetName 119 void 120 FreezeTransformationCommand::GetName(BString& name) 121 { 122 static BStringFormat format(B_TRANSLATE("Freeze {0, plural, " 123 "one{shape} other{shapes}}")); 124 format.Format(name, fCount); 125 } 126 127 // #pragma mark - 128 129 // _ApplyTransformation 130 void 131 FreezeTransformationCommand::_ApplyTransformation(PathSourceShape* shape, 132 const Transformable& transform) 133 { 134 // apply inverse of old shape transformation to every assigned path 135 int32 pathCount = shape->Paths()->CountItems(); 136 for (int32 i = 0; i < pathCount; i++) { 137 VectorPath* path = shape->Paths()->ItemAtFast(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 %" B_PRId32 " 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