1 #pragma once 2 3 #ifndef TVECTORIMAGE_INCLUDED 4 #define TVECTORIMAGE_INCLUDED 5 6 #include <memory> 7 8 #include "timage.h" 9 10 // da togliere spostando cose in altri file!! 11 #include "traster.h" 12 #include "tstream.h" 13 14 #include <set> 15 16 #undef DVAPI 17 #undef DVVAR 18 #ifdef TVECTORIMAGE_EXPORTS 19 #define DVAPI DV_EXPORT_API 20 #define DVVAR DV_EXPORT_VAR 21 #else 22 #define DVAPI DV_IMPORT_API 23 #define DVVAR DV_IMPORT_VAR 24 #endif 25 26 //#define NEW_REGION_FILL 27 #define DISEGNO_OUTLINE 0 28 29 //============================================================================= 30 // Forward declarations 31 class TVectorImageP; 32 class TStroke; 33 class TRegion; 34 class TRegionId; 35 class TColorStyle; 36 class TVectorRenderData; 37 class TRegionId; 38 class TFilledRegionInf; 39 namespace TThread { 40 class Mutex; 41 } 42 43 //============================================================================= 44 45 #define REGION_COMPUTING_PRECISION 128.0 46 47 const double c_newAutocloseTolerance = 1.15; 48 49 //----------------------------------------------------------------------------- 50 51 class VIStroke; 52 53 /*! 54 TVectorImage: describe a vector image. 55 A vector image is a set of strokes and regions. 56 \relates TImage 57 */ 58 class DVAPI TVectorImage final : public TImage { 59 class Imp; 60 int pickGroup(const TPointD &pos, bool onEnteredGroup) const; 61 62 public: 63 std::unique_ptr<Imp> m_imp; 64 65 struct IntersectionBranch { 66 int m_strokeIndex; 67 int m_style; 68 double m_w; 69 UINT m_currInter; 70 UINT m_nextBranch; 71 bool m_gettingOut; 72 }; 73 //! if the vectorimage is loaded from disc, loaded=true 74 TVectorImage(bool loaded = false); 75 virtual ~TVectorImage(); 76 getType()77 TImage::Type getType() const override { return VECTOR; } 78 79 /*!Set valid regions flags 80 call validateRegions() after region/stroke changes 81 */ 82 void validateRegions(bool state = false); 83 //! Get valid regions flags 84 /*! Call validateRegions() after region/stroke changes 85 */ 86 bool areValidRegions(); 87 88 //! Return a clone of image 89 TVectorImageP clone() const; 90 91 //! Create a new \b TImage 92 TImage *cloneImage() const override; 93 94 //! Transform a stroke using an affine \b TAffine 95 void transform(const TAffine &aff, bool doChangeThickness = false); 96 97 // usato solo in pli 98 //! Put a region in the regions' container 99 void putRegion(TRegion *region); 100 101 //! Return the regions' count 102 UINT getRegionCount() const; 103 //! Get a region at index position 104 TRegion *getRegion(UINT index) const; 105 //! Get a region at \b TRegionId id 106 TRegion *getRegion(TRegionId) const; 107 108 //! returns the region equivalent to region, 0 if does not exists. 109 TRegion *findRegion(const TRegion ®ion) const; 110 // calcola tutte le regioni che intersecano rect(e qualcuna in piu' a 111 // volte...) 112 void findRegions(const TRectD &rect); 113 114 //! Return the strokes' count 115 UINT getStrokeCount() const; 116 //! Get a \b TStroke stroke at index position 117 TStroke *getStroke(UINT index) const; 118 //! Get a \b VIStroke stroke at index position 119 VIStroke *getVIStroke(UINT index) const; 120 //! Get a \b VIStroke stroke at id 121 VIStroke *getStrokeById(int id) const; 122 123 //! Get the stroke index by id 124 int getStrokeIndexById(int id) const; 125 126 //! Get the stroke index by id 127 int getStrokeIndex(TStroke *stroke) const; 128 129 //! Group strokes in the \b fromIndex - \b toIndex range 130 /*! Only adjacent strokes can be grouped*/ 131 void group(int fromIndex, int count); 132 133 //! Ungroup all the strokes in the group of index \b index. 134 /*! Return the number of ungroped stroke.*/ 135 int ungroup(int index); 136 isStrokeGrouped(UINT index)137 bool isStrokeGrouped(UINT index) const { return getGroupDepth(index) > 0; } 138 //! Return a value grater of zero if stroke of index \b index is contained in 139 //! a group 140 /*! The returned number is the depth of the nested group containing the 141 * stroke.*/ 142 int getGroupDepth(UINT index) const; 143 144 //! it says if two strokes are in the same group, even qhen the image is 145 //! entered in a group. 146 147 bool sameSubGroup(int strokeIndex0, int strokeIndex1) const; 148 149 int getCommonGroupDepth(int strokeIndex0, int strokeIndex1) const; 150 151 //! Return -1 if two object are contained in the same group. 152 /*! Objects can be strokes or regions: they are identified by \b index1 and \b 153 index2. 154 If objects aren't in the same group, the method return the number of 155 equal level into the nested groups.*/ 156 int areDifferentGroup(UINT index1, bool isRegion1, UINT index2, 157 bool isRegion2) const; 158 159 // utility functions 160 //! Return true if two strokes has common parent groups. sameParentGroupStrokes(UINT index1,UINT index2)161 bool sameParentGroupStrokes(UINT index1, UINT index2) const { 162 int ret = areDifferentGroup(index1, false, index2, false); 163 return (ret == -1 || ret >= 1); 164 } 165 //! Return true if two objects are contained into the same group. sameGroup(UINT index1,UINT index2)166 bool sameGroup(UINT index1, UINT index2) const { 167 return areDifferentGroup(index1, false, index2, false) == -1; 168 } 169 //! Return true if a stroke and a region have common parent groups. sameGroupStrokeAndRegion(UINT strokeIndex,UINT regionIndex)170 bool sameGroupStrokeAndRegion(UINT strokeIndex, UINT regionIndex) const { 171 return areDifferentGroup(strokeIndex, false, regionIndex, true) == -1; 172 } 173 174 // entering and exiting groups 175 bool inCurrentGroup(int strokeIndex) const; 176 bool canEnterGroup(int strokeIndex) const; 177 bool selectable(int strokeIndex) const; 178 bool enterGroup(int index); 179 180 // return -1 if no possible to exit, otherwise a stroke index which has same 181 // id of the exiting group 182 int exitGroup(); 183 bool isEnteredGroupStroke(int index) const; 184 bool canMoveStrokes(int strokeIndex, int count, int moveBefore) const; 185 // returns depth of group inside. 186 int isInsideGroup() const; 187 188 int pickGroup(const TPointD &pos) const; 189 int getGroupByStroke(UINT index) const; 190 int getGroupByRegion(UINT index) const; 191 192 /*! 193 get the stroke nearest at point 194 \note outw is stroke parameter w in [0,1] 195 \par p [input] is point nearest stroke 196 \par outw [output] is parameter of minimum in stroke 197 \par strokeIndex [output] is index of stroke in vector image 198 \par dist2 [output] is the square value of distance 199 \ret true if a value is found 200 */ 201 bool getNearestStroke(const TPointD &p, 202 203 // output 204 double &outw, UINT &strokeIndex, double &dist2, 205 bool inCurrentGroup = true) const; 206 207 //! Enable or disable the style of a stroke according to the \b enable param. 208 static void enableStrokeStyle(int index, bool enable); 209 //! Return true if the style of the stroke identified by \b index is enabled. 210 static bool isStrokeStyleEnabled(int index); 211 212 //! Remove the stroke of index \b index and if \b doComputeRegions is true 213 //! recompute the regions 214 TStroke *removeStroke(int index, bool doComputeRegions = true); 215 //! Remove the strokes identified by indexes in the vector \b toBeRemoved 216 /*! If \b deleteThem is true strokes are really delete; 217 if \b doComputeRegions is true recompute the regions*/ 218 void removeStrokes(const std::vector<int> &tobeRemoved, bool deleteThem, 219 bool recomputeRegions); 220 221 //! Delete the \b TStroke stroke of index \b index 222 void deleteStroke(int index); 223 //! Delete the \b VIStroke stroke 224 void deleteStroke(VIStroke *stroke); 225 226 //! Add a stroke at the end of the vector; returns position of the stroke (or 227 //! -1 if not added) 228 int addStroke(TStroke *, bool discardPoints = true); 229 int addStrokeToGroup(TStroke *stroke, int strokeIndex); 230 //! Replace the stroke at index \b index with \b newStroke 231 void replaceStroke(int index, TStroke *newStroke); 232 233 //! Insert a \b VIStroke \b vs at index \b strokeIndex 234 void insertStrokeAt(VIStroke *vs, int strokeIndex, 235 bool recomputeRegions = true); //! Move \b count strokes 236 //! starting from \b 237 //! fromIndex before the 238 //! stroke identified by 239 //! the \b moveBefore 240 //! index. 241 void moveStrokes(int fromIndex, int count, int moveBefore); 242 //! Find regions of a \b TVectorImage 243 void findRegions(); 244 245 // Gmt. VA TOLTO IL PRIMA POSSIBILE. 246 // E' una pessima cosa rendere platform dependent l'interfaccia pubblica di una 247 // classe cosi' importante come la VectorImage 248 #if defined(LINUX) || defined(FREEBSD) || defined(MACOSX) 249 void render(const TVectorRenderData &rd, TRaster32P &ras); 250 #endif 251 252 //! Make the rendering of the vector image, return a \b TRaster32P with the 253 //! image rendered 254 TRaster32P render(bool onlyStrokes); 255 //! Return the region which contains \b p, if none regions contains \b p 256 //! return 0 257 TRegion *getRegion(const TPointD &p); 258 259 //! Fill the region which contains \b p with \b styleId. it returns the style 260 //! of the region before filling or -1 if not filled. 261 int fill(const TPointD &p, int styleId, bool onlyEmpty = false); 262 //! Fill all the regions and strokes contained in \b selectArea or contained 263 //! into the regions formed by the stroke \b s with the style \b styleId. 264 /*! If \b onlyUnfilled is true, only regions filled with the style 0 are 265 filled with the new stile. 266 If \b fillAreas is true regions are filled. 267 If \b fillLines is true stroke are filled.*/ 268 bool selectFill(const TRectD &selectArea, TStroke *s, int styleId, 269 bool onlyUnfilled, bool fillAreas, bool fillLines); 270 271 //! Fill all regions contained in the \b stroke area with \b styleIndex 272 void areaFill(TStroke *stroke, int styleIndex, bool onlyUnfilled); 273 //! Fill the stroke which contains \b p with \b newStyleId; it returns the 274 //! style of stroke before filling or -1 if not filled. 275 int fillStrokes(const TPointD &p, int newStyleId); 276 277 //! Return true if \b computeRegion method was called 278 bool isComputedRegionAlmostOnce() const; 279 280 //! Return the image bounding box in the image coordinate system 281 TRectD getBBox() const override; 282 283 //! Call the following method after stroke modification 284 //! \note you must specify, using the second argument, whether the 285 //! modification was a reflection 286 void notifyChangedStrokes(const std::vector<int> &strokeIndexArray, 287 const std::vector<TStroke *> &oldStrokeArray, 288 bool areFlipped = false); 289 290 //! Call the following method after stroke modification 291 void notifyChangedStrokes(int strokeIndex, TStroke *oldStroke = 0, 292 bool isFlipped = false); 293 294 UINT getFillData(std::unique_ptr<IntersectionBranch[]> &v); 295 void setFillData(std::unique_ptr<IntersectionBranch[]> const &v, UINT size, 296 bool doComputeRegions = true); 297 298 void drawAutocloses(const TVectorRenderData &rd) const; // debug method 299 300 /*! Includes a (transformed) copy of imgs in this. If setSelected==true then 301 selects imported strokes. 302 It also includes the color informations. 303 Try to assign the same stroke ids (if unused) 304 */ 305 void enableRegionComputing(bool enabled, bool notIntersectingStrokes); 306 307 /*! if enabled, region edges are joined together when possible. for flash 308 * render, should be disabled! 309 */ 310 void enableMinimizeEdges(bool enabled); 311 /*! Creates a new Image using the selected strokes. If removeFlag==true then 312 removes selected strokes 313 It includes (in the new image) the color informations too. 314 It mantains stroke ids. 315 */ 316 TVectorImageP splitSelected(bool removeFlag); 317 318 //! Merge the image with the \b img. 319 int mergeImage(const TVectorImageP &img, const TAffine &affine, 320 bool sameStrokeId = true); 321 322 int mergeImage(const TVectorImageP &img, const TAffine &affine, 323 const std::map<int, int> &styleTable, 324 bool sameStrokeId = true); 325 //! Merge the image with the vector of image \b images. 326 void mergeImage(const std::vector<const TVectorImage *> &images); 327 328 //! Insert the \b TVectorImageP \b img 329 void insertImage(const TVectorImageP &img, 330 const std::vector<int> &dstIndices); 331 TVectorImageP splitImage(const std::vector<int> &indices, bool removeFlag); 332 333 //! Return the used styles in the image 334 void getUsedStyles(std::set<int> &styles) const; 335 //! Reassign all stroke's style 336 void reassignStyles(std::map<int, int> &table); 337 338 //! Transfer the stroke style of the \b sourceStroke in the \b sourceImage to 339 //! the style 340 static void transferStrokeColors(TVectorImageP sourceImage, int sourceStroke, 341 TVectorImageP destinationImage, 342 int destinationStroke); 343 //! Set the edges of the stroke identified by \b strokeIndex with the styles 344 //! \b leftColorIndex and \brightColorIndex. 345 void setEdgeColors(int strokeIndex, int leftColorIndex, int rightColorIndex); 346 347 /*! This functions splits stroke with index 'strokeIndex' in n+1 strokes, 348 where n is the size of vector sortedW, 349 cutting it in points w specified in sortedW. SortedW must be sorted in 350 ascending order. 351 Resulting strokes are put in VectorImage in position 352 strokeIndex,strokeIndex+1, ... strokeIndex+n. 353 Information on fill colors are maintened, as much as possible. */ 354 void splitStroke(int strokeIndex, 355 const std::vector<DoublePair> &sortedWRanges); 356 VIStroke *joinStroke(int index1, int index2, int cpIndex1, int cpIndex2, 357 bool isSmooth); 358 VIStroke *extendStroke(int index, const TThickPoint &p, int cpIndex, 359 bool isSmooth); 360 /*! this method removes the parts of the stroke that are not bounds of 361 regions. only ending parts are removed. 362 If the entire stroke is not bounding any region, it is kept entitely. 363 it returns the original stroke (for undo)*/ 364 TStroke *removeEndpoints(int strokeIndex); 365 366 /*! this method replaces the stroke at index with oldstroke. Oldstroke is 367 supposed to contain 368 existing stroke. this method is used for undoing removeEndpoints . */ 369 void restoreEndpoints(int index, TStroke *oldStroke); 370 371 //! Set the autoclose tolerance to the specified value. 372 void setAutocloseTolerance(double val); 373 //! Return the autoclose tolerance. 374 double getAutocloseTolerance() const; 375 376 //! forces the recomputing of all regions (it is actually done only after 377 //! having loaded the vectorimage) 378 void recomputeRegionsIfNeeded(); 379 380 /*! Remove all image strokes and all image regions with style index contained 381 * in \b styleIds vector.*/ 382 void eraseStyleIds(const std::vector<int> styleIds); 383 384 TThread::Mutex *getMutex() const; 385 386 #ifdef _DEBUG 387 void checkIntersections(); 388 #endif 389 390 void computeRegion(const TPointD &p, int styleId); 391 392 #ifdef NEW_REGION_FILL 393 void resetRegionFinder(); 394 #endif 395 396 private: // not implemented 397 TVectorImage(const TVectorImage &); 398 TVectorImage &operator=(const TVectorImage &); 399 }; 400 401 DVAPI VIStroke *cloneVIStroke(VIStroke *vs); 402 DVAPI void deleteVIStroke(VIStroke *vs); 403 404 DVAPI void getClosingPoints(const TRectD &rect, double fac, 405 const TVectorImageP &vi, 406 std::vector<std::pair<int, double>> &startPoints, 407 std::vector<std::pair<int, double>> &endPoints); 408 409 //----------------------------------------------------------------------------- 410 411 #ifdef _WIN32 412 template class DVAPI TSmartPointerT<TVectorImage>; 413 template class DVAPI TDerivedSmartPointerT<TVectorImage, TImage>; 414 #endif 415 416 class DVAPI TVectorImageP final 417 : public TDerivedSmartPointerT<TVectorImage, TImage> { 418 public: TVectorImageP()419 TVectorImageP() {} TVectorImageP(TVectorImage * image)420 TVectorImageP(TVectorImage *image) : DerivedSmartPointer(image) {} TVectorImageP(TImageP image)421 TVectorImageP(TImageP image) : DerivedSmartPointer(image) {} 422 #if !defined(_WIN32) TVectorImageP(TImage * image)423 TVectorImageP(TImage *image) : DerivedSmartPointer(TImageP(image)) {} 424 #endif TImageP()425 operator TImageP() { return TImageP(m_pointer); } 426 }; 427 428 //----------------------------------------------------------------------------- 429 430 // GMT: DA TOGLIERE. vedi sopra 431 #if defined(LINUX) || defined(FREEBSD) 432 DVAPI void hardRenderVectorImage(const TVectorRenderData &rd, TRaster32P &r, 433 const TVectorImageP &vimg); 434 #endif 435 //----------------------------------------------------------------------------- 436 437 //============================================================================= 438 439 class DVAPI TInputStreamInterface { 440 public: TInputStreamInterface()441 TInputStreamInterface() {} ~TInputStreamInterface()442 virtual ~TInputStreamInterface() {} 443 444 virtual TInputStreamInterface &operator>>(double &) = 0; 445 virtual TInputStreamInterface &operator>>(int &) = 0; 446 virtual TInputStreamInterface &operator>>(std::string &) = 0; 447 virtual TInputStreamInterface &operator>>(UCHAR &) = 0; 448 virtual TInputStreamInterface &operator>>(USHORT &) = 0; 449 virtual TInputStreamInterface &operator>>(TRaster32P &) = 0; 450 virtual TInputStreamInterface &operator>>(TPixel32 &pixel); 451 versionNumber()452 virtual VersionNumber versionNumber() const { return VersionNumber(); } 453 }; 454 455 //----------------------------------------------------------------------------- 456 457 class DVAPI TOutputStreamInterface { 458 public: TOutputStreamInterface()459 TOutputStreamInterface() {} ~TOutputStreamInterface()460 virtual ~TOutputStreamInterface() {} 461 462 virtual TOutputStreamInterface &operator<<(double) = 0; 463 virtual TOutputStreamInterface &operator<<(int) = 0; 464 virtual TOutputStreamInterface &operator<<(std::string) = 0; 465 virtual TOutputStreamInterface &operator<<(UCHAR) = 0; 466 virtual TOutputStreamInterface &operator<<(USHORT) = 0; 467 virtual TOutputStreamInterface &operator<<(const TRaster32P &) = 0; 468 virtual TOutputStreamInterface &operator<<(const TPixel32 &pixel); 469 }; 470 471 #if DISEGNO_OUTLINE == 1 472 extern int CurrStrokeIndex; 473 #include "tvectorimage.h" 474 extern const TVectorImage *CurrVimg; 475 #else 476 #ifndef DISEGNO_OUTLINE 477 *&^&%^^$%&^%$(^( 478 #endif 479 #endif 480 481 #endif 482