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