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 &region) 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