From 6bd53158fb1a412a2d1fc98dca738b6a42690761 Mon Sep 17 00:00:00 2001
From: Shinya Kitaoka <skitaoka@gmail.com>
Date: Apr 26 2016 15:58:01 +0000
Subject: Merge pull request #252 from opentoonz/fix/revert-to-fix-vector-rendering


Revert refactoring for vector rendering
---

diff --git a/toonz/sources/common/tvectorimage/tcomputeregions.cpp b/toonz/sources/common/tvectorimage/tcomputeregions.cpp
index 6af75b2..9c9fa37 100644
--- a/toonz/sources/common/tvectorimage/tcomputeregions.cpp
+++ b/toonz/sources/common/tvectorimage/tcomputeregions.cpp
@@ -1817,7 +1817,12 @@ void getClosingPoints(const TRectD &rect, double fac, const TVectorImageP &vi,
 			if (s2->getChunkCount() == 1)
 				continue;
 
+#ifdef NEW_REGION_FILL
+			double autoTol = 0;
+#else
 			double autoTol = vi->getAutocloseTolerance();
+#endif
+
 			double enlarge1 = (autoTol + 0.7) * (s1->getMaxThickness() > 0 ? s1->getMaxThickness() : 2.5) + fac;
 			double enlarge2 = (autoTol + 0.7) * (s2->getMaxThickness() > 0 ? s2->getMaxThickness() : 2.5) + fac;
 
@@ -2747,6 +2752,10 @@ void printStrokes1(vector<VIStroke *> &v, int size);
 // Trova le regioni in una TVectorImage
 int TVectorImage::Imp::computeRegions()
 {
+#ifdef NEW_REGION_FILL
+	return 0;
+#endif
+
 #if defined(_DEBUG) && !defined(MACOSX)
 	TStopWatch stopWatch;
 	stopWatch.start(true);
diff --git a/toonz/sources/common/tvectorimage/tvectorimage.cpp b/toonz/sources/common/tvectorimage/tvectorimage.cpp
index 745ccb5..b51aaaa 100644
--- a/toonz/sources/common/tvectorimage/tvectorimage.cpp
+++ b/toonz/sources/common/tvectorimage/tvectorimage.cpp
@@ -86,7 +86,14 @@ TVectorImage::Imp: implementation of TVectorImage class
 
 TVectorImage::Imp::Imp(TVectorImage *vi)
 	: m_areValidRegions(false), m_notIntersectingStrokes(false), m_computeRegions(true), m_autocloseTolerance(c_newAutocloseTolerance), m_maxGroupId(1), m_maxGhostGroupId(1), m_mutex(new TThread::Mutex()), m_vi(vi), m_intersectionData(0), m_computedAlmostOnce(false), m_justLoaded(false), m_insideGroup(TGroupId()), m_minimizeEdges(true)
+#ifdef NEW_REGION_FILL
+	  ,
+	  m_regionFinder(0)
+#endif
 {
+#ifdef NEW_REGION_FILL
+	resetRegionFinder();
+#endif
 	initRegionsData();
 }
 
@@ -671,11 +678,13 @@ TRaster32P TVectorImage::render(bool onlyStrokes)
 
 TRegion *TVectorImage::getRegion(const TPointD &p)
 {
+#ifndef NEW_REGION_FILL
 	if (!isComputedRegionAlmostOnce())
 		return 0;
 
 	if (!m_imp->m_areValidRegions)
 		m_imp->computeRegions();
+#endif
 
 	return m_imp->getRegion(p);
 }
@@ -721,6 +730,15 @@ int TVectorImage::fillStrokes(const TPointD &p, int styleId)
 	return -1;
 }
 
+//-----------------------------------------------------------------------------
+
+#ifdef NEW_REGION_FILL
+
+void TVectorImage::resetRegionFinder()
+{
+	m_imp->resetRegionFinder();
+}
+#else
 //------------------------------------------------------------------
 
 int TVectorImage::fill(const TPointD &p, int newStyleId, bool onlyEmpty)
@@ -734,7 +752,41 @@ int TVectorImage::fill(const TPointD &p, int newStyleId, bool onlyEmpty)
 		m_imp->computeRegions();
 	return m_imp->fill(p, newStyleId);
 }
+#endif
+
+//-----------------------------------------------------------------------------
+/*
+void TVectorImage::autoFill(int styleId)
+{
+m_imp->autoFill(styleId, true);
+}
+
+void TVectorImage::Imp::autoFill(int styleId, bool oddLevel)
+{
+if (!m_areValidRegions)
+  computeRegions(); 
+for (UINT i = 0; i<m_regions.size(); i++)
+  {
+  if (oddLevel)
+    m_regions[i]->setStyle(styleId);
+  m_regions[i]->autoFill(styleId, !oddLevel);
+  }
+}
+*/
+//-----------------------------------------------------------------------------
+/*
+void TRegion::autoFill(int styleId, bool oddLevel)
+{
+for (UINT i = 0; i<getSubregionCount(); i++)
+  {
+  TRegion* r = getSubregion(i);
+  if (oddLevel)
+    r->setStyle(styleId);
+  r->autoFill(styleId, !oddLevel);
+  }
 
+}
+*/
 //-----------------------------------------------------------------------------
 
 int TVectorImage::Imp::fill(const TPointD &p, int styleId)
@@ -778,14 +830,12 @@ bool TVectorImage::Imp::selectFill(const TRectD &selArea, TStroke *s, int newSty
 		aux.findRegions();
 		for (UINT j = 0; j < aux.getRegionCount(); j++) {
 			TRegion *r0 = aux.getRegion(j);
-			if (fillAreas) {
+			if (fillAreas)
 				for (UINT i = 0; i < m_regions.size(); i++) {
 					TRegion *r1 = m_regions[i];
 
-					if ((m_insideGroup != TGroupId())
-						&& !m_insideGroup.isParentOf(m_strokes[r1->getEdge(0)->m_index]->m_groupId)) {
-							continue;
-					}
+					if (m_insideGroup != TGroupId() && !m_insideGroup.isParentOf(m_strokes[r1->getEdge(0)->m_index]->m_groupId))
+						continue;
 
 					if ((!onlyUnfilled || r1->getStyle() == 0) &&
 						r0->contains(*r1)) {
@@ -793,8 +843,7 @@ bool TVectorImage::Imp::selectFill(const TRectD &selArea, TStroke *s, int newSty
 						hitSome = true;
 					}
 				}
-			}
-			if (fillLines) {
+			if (fillLines)
 				for (UINT i = 0; i < m_strokes.size(); i++) {
 					if (!inCurrentGroup(i))
 						continue;
@@ -806,35 +855,40 @@ bool TVectorImage::Imp::selectFill(const TRectD &selArea, TStroke *s, int newSty
 						hitSome = true;
 					}
 				}
-			}
 		}
 		aux.removeStroke(0);
 		return hitSome;
 	}
 
 	// rect fill
-	if (fillAreas) {
-		for (std::size_t i = 0, size = m_regions.size(); i < size; i++) {
-			int index;
-			UINT j = 0;
 
-			do {
-				index = m_regions[i]->getEdge(j++)->m_index;
-			}  while ((index < 0) && (j < m_regions[i]->getEdgeCount()));
+	if (fillAreas)
+#ifndef NEW_REGION_FILL
+		for (UINT i = 0; i < m_regions.size(); i++) {
+			int index, j = 0;
 
-			// if index<0, means that the region is purely of autoclose strokes!
-			if ((m_insideGroup != TGroupId())
-				&& (index >= 0) && !m_insideGroup.isParentOf(m_strokes[index]->m_groupId)) {
+			do
+				index = m_regions[i]->getEdge(j++)->m_index;
+			while (index < 0 && j < (int)m_regions[i]->getEdgeCount());
+			//if index<0, means that the region is purely of autoclose strokes!
+			if (m_insideGroup != TGroupId() && index >= 0 && !m_insideGroup.isParentOf(m_strokes[index]->m_groupId))
 				continue;
-			}
-			if (onlyUnfilled && (m_regions[i]->getStyle() != 0)) {
-			} else {
+			if (!onlyUnfilled || m_regions[i]->getStyle() == 0)
 				hitSome |= m_regions[i]->selectFill(selArea, newStyleId);
-			}
 		}
+#else
+
+		findRegions(selArea);
+
+	for (UINT i = 0; i < m_regions.size(); i++) {
+		if (m_insideGroup != TGroupId() && !m_insideGroup.isParentOf(m_strokes[m_regions[i]->getEdge(0)->m_index]->m_groupId))
+			continue;
+		if (!onlyUnfilled || m_regions[i]->getStyle() == 0)
+			hitSome |= m_regions[i]->selectFill(selArea, newStyleId);
 	}
+#endif
 
-	if (fillLines) {
+	if (fillLines)
 		for (UINT i = 0; i < m_strokes.size(); i++) {
 			if (!inCurrentGroup(i))
 				continue;
@@ -846,8 +900,6 @@ bool TVectorImage::Imp::selectFill(const TRectD &selArea, TStroke *s, int newSty
 				hitSome = true;
 			}
 		}
-	}
-
 	return hitSome;
 }
 
diff --git a/toonz/sources/common/tvectorimage/tvectorimageP.h b/toonz/sources/common/tvectorimage/tvectorimageP.h
index 6fb06e9..faf64d6 100644
--- a/toonz/sources/common/tvectorimage/tvectorimageP.h
+++ b/toonz/sources/common/tvectorimage/tvectorimageP.h
@@ -199,6 +199,11 @@ public:
 
 #endif
 
+#ifdef NEW_REGION_FILL
+	TRegionFinder *m_regionFinder;
+	void resetRegionFinder();
+#endif
+
 private:
 	void findRegions(const TRectD &rect);
 	int computeIntersections();
diff --git a/toonz/sources/image/pli/tiio_pli.cpp b/toonz/sources/image/pli/tiio_pli.cpp
index 2eef5cc..b1b41eb 100644
--- a/toonz/sources/image/pli/tiio_pli.cpp
+++ b/toonz/sources/image/pli/tiio_pli.cpp
@@ -295,7 +295,9 @@ TImageP TImageReaderPli::load()
 
 void readRegionVersion4x(IntersectionDataTag *tag, TVectorImage *img)
 {
+#ifndef NEW_REGION_FILL
 	img->setFillData(tag->m_branchArray, tag->m_branchCount);
+#endif
 }
 
 //-----------------------------------------------------------------------------
@@ -359,34 +361,42 @@ TImageP TImageReaderPli::doLoad()
 	CreateStrokeData strokeData;
 
 	// preparo l'immagine da restituire
-	TSmartPointerT<TVectorImage> outVectImage(new TVectorImage(true));
+	TVectorImage
+		*outVectImage = new TVectorImage(true);
+	// fisso il colore di default a nero opaco
+	//TPixel currentColor=TPixel::Black;
+	//TStrokeStyle *currStyle = NULL;
+	// chiudo tutto dentro un blocco try per  cautelarmi
+	//  dalle eccezioni generate in lettura
+	//try
+	//{
+	// un contatore
+	UINT i;
 	outVectImage->setAutocloseTolerance(m_lrp->m_pli->getAutocloseTolerance());
 
-	ImageTag* imageTag = m_lrp->m_pli->loadFrame(m_frameId);
-	if (!imageTag) {
+	ImageTag *imageTag;
+
+	imageTag = m_lrp->m_pli->loadFrame(m_frameId);
+	if (!imageTag)
 		throw TImageException(m_path, "Corrupted or invalid image data");
-	}
-	m_lrp->m_mapOfImage[m_frameId].second = true;
+
+	if (m_lrp->m_mapOfImage[m_frameId].second == false)
+		m_lrp->m_mapOfImage[m_frameId].second = true;
 
 	// per tutti gli oggetti presenti nel tag
-	for (UINT i = 0; i < imageTag->m_numObjects; i++) {
+	for (i = 0; i < imageTag->m_numObjects; i++) {
 		switch (imageTag->m_object[i]->m_type) {
-		case PliTag::GROUP_GOBJ:
+		case PliTag::GROUP_GOBJ: {
 			assert(((GroupTag *)imageTag->m_object[i])->m_type == GroupTag::STROKE);
-			createGroup((GroupTag *)imageTag->m_object[i], outVectImage.getPointer(), strokeData);
-			break;
-
-		case PliTag::INTERSECTION_DATA_GOBJ:
-			readRegionVersion4x((IntersectionDataTag *)imageTag->m_object[i], outVectImage.getPointer());
-			break;
+			createGroup((GroupTag *)imageTag->m_object[i], outVectImage, strokeData);
+		}
+			CASE PliTag::INTERSECTION_DATA_GOBJ : readRegionVersion4x((IntersectionDataTag *)imageTag->m_object[i], outVectImage);
 
-		case PliTag::THICK_QUADRATIC_CHAIN_GOBJ:
 			// aggiunge le stroke quadratiche
-			createStroke((ThickQuadraticChainTag *)imageTag->m_object[i], outVectImage.getPointer(), strokeData);
-			break;
+			CASE PliTag::THICK_QUADRATIC_CHAIN_GOBJ : createStroke((ThickQuadraticChainTag *)imageTag->m_object[i], outVectImage, strokeData);
 
-		case PliTag::COLOR_NGOBJ:
 			// aggiunge curve quadratiche con spessore costante
+			CASE PliTag::COLOR_NGOBJ:
 			{
 				ColorTag *colorTag = (ColorTag *)imageTag->m_object[i];
 
@@ -395,20 +405,29 @@ TImageP TImageReaderPli::doLoad()
 				// isSketch=(colorTag->m_color[0] < c_maxSketchColorNum);
 				// isSketch=(colorTag->m_color[0] < c_maxSketchColorNum);
 			}
-			break;
 
-		case PliTag::OUTLINE_OPTIONS_GOBJ:
 			// adds outline options data
-			strokeData.m_options = ((StrokeOutlineOptionsTag *)imageTag->m_object[i])->m_options;
-			break;
-		}
-	}
+			CASE PliTag::OUTLINE_OPTIONS_GOBJ : strokeData.m_options = ((StrokeOutlineOptionsTag *)imageTag->m_object[i])->m_options;
+
+		DEFAULT:;
+		} // switch(groupTag->m_object[j]->m_type)
+	}	 // for (i=0; i<imageTag->m_numObjects; i++)
+
+//} // try
+
+//catch(...) // cosi' e' inutile o raccolgo qualcosa prima di rilanciare o lo elimino
+//{
+//  throw;
+// }
+
+//  if (regionsComputed) //WARNING !!! la seedFill mette il flag a ValidRegion a TRUE
+//    outVectImage->seedFill(); //le vecchie immagini hanno il seed (version<3.1)
 
 #ifdef _DEBUG
 	outVectImage->checkIntersections();
 #endif
 
-	return TImageP(outVectImage.releasePointer());
+	return TImageP(outVectImage);
 }
 
 //-----------------------------------------------------------------------------
diff --git a/toonz/sources/include/ext/meshtexturizer.h b/toonz/sources/include/ext/meshtexturizer.h
index 99fadbe..99724e2 100644
--- a/toonz/sources/include/ext/meshtexturizer.h
+++ b/toonz/sources/include/ext/meshtexturizer.h
@@ -117,7 +117,7 @@ private:
 
 struct MeshTexturizer::TextureData {
 	struct TileData //!  Data structure for a texture tile.
-	{
+		{
 		GLuint m_textureId;	//!< OpenGL texture identifier.
 		TRectD m_tileGeometry; //!< The tile's world geometry.
 	};
@@ -132,15 +132,15 @@ public:
 
 	~TextureData()
 	{
-		for (auto const& tile : m_tileDatas) {
-			glDeleteTextures(1, &tile.m_textureId);
-		}
+		int t, tilesCount = m_tileDatas.size();
+		for (t = 0; t < tilesCount; ++t)
+			glDeleteTextures(1, &m_tileDatas[t].m_textureId);
 	}
 
 private:
 	// Not copyable
-	TextureData(const TextureData &) = delete;
-	TextureData &operator=(const TextureData &) = delete;
+	TextureData(const TextureData &);
+	TextureData &operator=(const TextureData &);
 };
 
 #endif // MESHTEXTURIZER_H
diff --git a/toonz/sources/include/tgl.h b/toonz/sources/include/tgl.h
index 1a4f7e7..d54f644 100644
--- a/toonz/sources/include/tgl.h
+++ b/toonz/sources/include/tgl.h
@@ -3,10 +3,13 @@
 #ifndef TGL_INCLUDED
 #define TGL_INCLUDED
 
+//#include "tgeometry.h"
 #include "tmachine.h"
 
 #ifdef _WIN32
 #include <windows.h>
+//#endif
+
 #include <GL/gl.h>
 #include <GL/glu.h>
 #include <GL/glut.h>
diff --git a/toonz/sources/include/tpixelutils.h b/toonz/sources/include/tpixelutils.h
index b10e15c..96b2975 100644
--- a/toonz/sources/include/tpixelutils.h
+++ b/toonz/sources/include/tpixelutils.h
@@ -356,25 +356,25 @@ DVAPI inline void premult(TPixel32 &pix)
 
 DVAPI inline void premult(TPixel64 &pix)
 {
-	pix.r = static_cast<TPixel64::Channel>(pix.r * pix.m / 65535.0);
-	pix.g = static_cast<TPixel64::Channel>(pix.g * pix.m / 65535.0);
-	pix.b = static_cast<TPixel64::Channel>(pix.b * pix.m / 65535.0);
+	pix.r = pix.r * pix.m / 65535.0;
+	pix.g = pix.g * pix.m / 65535.0;
+	pix.b = pix.b * pix.m / 65535.0;
 }
 
 DVAPI inline void depremult(TPixel32 &pix)
 {
 	float fac = 255.0f / pix.m;
-	pix.r = static_cast<TPixel32::Channel>(tmin(pix.r * fac, 255.0f));
-	pix.g = static_cast<TPixel32::Channel>(tmin(pix.g * fac, 255.0f));
-	pix.b = static_cast<TPixel32::Channel>(tmin(pix.b * fac, 255.0f));
+	pix.r = tmin(pix.r * fac, 255.0f);
+	pix.g = tmin(pix.g * fac, 255.0f);
+	pix.b = tmin(pix.b * fac, 255.0f);
 }
 
 DVAPI inline void depremult(TPixel64 &pix)
 {
 	double fac = 65535.0 / pix.m;
-	pix.r = static_cast<TPixel64::Channel>(tmin(pix.r * fac, 65535.0));
-	pix.g = static_cast<TPixel64::Channel>(tmin(pix.g * fac, 65535.0));
-	pix.b = static_cast<TPixel64::Channel>(tmin(pix.b * fac, 65535.0));
+	pix.r = tmin(pix.r * fac, 65535.0);
+	pix.g = tmin(pix.g * fac, 65535.0);
+	pix.b = tmin(pix.b * fac, 65535.0);
 }
 
 //-----------------------------------------------------------------------------
@@ -402,27 +402,27 @@ DVAPI inline TPixel32 premultiply(const TPixel32 &pix)
 DVAPI inline TPixel64 premultiply(const TPixel64 &pix)
 {
 	return TPixel64(
-		static_cast<TPixel64::Channel>(pix.r * pix.m / 65535.0),
-		static_cast<TPixel64::Channel>(pix.g * pix.m / 65535.0),
-		static_cast<TPixel64::Channel>(pix.b * pix.m / 65535.0),
+		pix.r * pix.m / 65535.0,
+		pix.g * pix.m / 65535.0,
+		pix.b * pix.m / 65535.0,
 		pix.m);
 }
 
 DVAPI inline TPixel32 depremultiply(const TPixel32 &pix)
 {
 	return TPixel32(
-		static_cast<TPixel32::Channel>(pix.r * 255.0 / pix.m),
-		static_cast<TPixel32::Channel>(pix.g * 255.0 / pix.m),
-		static_cast<TPixel32::Channel>(pix.b * 255.0 / pix.m),
+		pix.r * 255.0 / pix.m,
+		pix.g * 255.0 / pix.m,
+		pix.b * 255.0 / pix.m,
 		pix.m);
 }
 
 DVAPI inline TPixel64 depremultiply(const TPixel64 &pix)
 {
 	return TPixel64(
-		static_cast<TPixel64::Channel>(pix.r * 65535.0 / pix.m),
-		static_cast<TPixel64::Channel>(pix.g * 65535.0 / pix.m),
-		static_cast<TPixel64::Channel>(pix.b * 65535.0 / pix.m),
+		pix.r * 65535.0 / pix.m,
+		pix.g * 65535.0 / pix.m,
+		pix.b * 65535.0 / pix.m,
 		pix.m);
 }
 
diff --git a/toonz/sources/include/tsmartpointer.h b/toonz/sources/include/tsmartpointer.h
index 14e3cfb..346f1c0 100644
--- a/toonz/sources/include/tsmartpointer.h
+++ b/toonz/sources/include/tsmartpointer.h
@@ -167,12 +167,6 @@ public:
 
 	T *getPointer() const { return m_pointer; }
 
-	T* releasePointer() {
-		T* p = m_pointer;
-		m_pointer = nullptr;
-		return p;
-	}
-
 	bool operator!() const { return m_pointer == 0; }
 	operator bool() const { return m_pointer != 0; }
 
diff --git a/toonz/sources/include/tvectorimage.h b/toonz/sources/include/tvectorimage.h
index 56a3b47..c9cd769 100644
--- a/toonz/sources/include/tvectorimage.h
+++ b/toonz/sources/include/tvectorimage.h
@@ -21,6 +21,7 @@
 #define DVVAR DV_IMPORT_VAR
 #endif
 
+//#define NEW_REGION_FILL
 #define DISEGNO_OUTLINE 0
 
 //=============================================================================
@@ -350,6 +351,10 @@ public:
 
 	void computeRegion(const TPointD &p, int styleId);
 
+#ifdef NEW_REGION_FILL
+	void resetRegionFinder();
+#endif
+
 private: //not implemented
 	TVectorImage(const TVectorImage &);
 	TVectorImage &operator=(const TVectorImage &);
diff --git a/toonz/sources/tnzext/meshtexturizer.cpp b/toonz/sources/tnzext/meshtexturizer.cpp
index e1fddf3..16f8557 100644
--- a/toonz/sources/tnzext/meshtexturizer.cpp
+++ b/toonz/sources/tnzext/meshtexturizer.cpp
@@ -158,16 +158,15 @@ void MeshTexturizer::Imp::allocateTextures(int groupIdx, const TRaster32P &ras, 
 
 	// Test the specified texture allocation
 	if (testTextureAlloc(textureLx, textureLy)) {
-		TPointD const scale(
-			data->m_geom.getLx() / ras->getLx(),
-			data->m_geom.getLy() / ras->getLy());
-		TRectD const tileGeom(
+		TPointD scale(data->m_geom.getLx() / (double)ras->getLx(),
+					  data->m_geom.getLy() / (double)ras->getLy());
+		TRectD tileGeom(
 			TRectD(
-				scale.x * (x             - TOTAL_BORDER), scale.y * (y             - TOTAL_BORDER),
+				scale.x * (x - TOTAL_BORDER), scale.y * (y - TOTAL_BORDER),
 				scale.x * (x + textureLx + TOTAL_BORDER), scale.y * (y + textureLy + TOTAL_BORDER)) +
 			data->m_geom.getP00());
 
-		GLuint const texId = textureAlloc(ras, aux, x, y, textureLx, textureLy, premultiplied);
+		GLuint texId = textureAlloc(ras, aux, x, y, textureLx, textureLy, premultiplied);
 
 		TextureData::TileData td = {texId, tileGeom};
 		data->m_tileDatas.push_back(td);
diff --git a/toonz/sources/tnzext/meshutils.cpp b/toonz/sources/tnzext/meshutils.cpp
index 52d4e16..4580bf2 100644
--- a/toonz/sources/tnzext/meshutils.cpp
+++ b/toonz/sources/tnzext/meshutils.cpp
@@ -12,8 +12,6 @@
 
 #include "ext/meshutils.h"
 
-#include <array>
-
 //********************************************************************************************
 //    Templated drawing functions
 //********************************************************************************************
@@ -65,24 +63,23 @@ inline void tglDrawFaces(const TMeshImage &meshImage, ColorFunction colorFunctio
 {
 	glBegin(GL_TRIANGLES);
 
-	int i = 0;
-	for (auto const& mesh : meshImage.meshes()) {
-		tcg::list<TTextureVertex> const & vertices = mesh->vertices();
-		int const m = i++;
+	int m, mCount = meshImage.meshes().size();
+	for (m = 0; m != mCount; ++m) {
+		const TTextureMesh &mesh = *meshImage.meshes()[m];
+		const tcg::list<TTextureVertex> &vertices = mesh.vertices();
 
 		// Draw the mesh wireframe
-		int j = 0;
-		for (auto const& ft : mesh->faces()) {
-			int const index = j++;
+		TTextureMesh::faces_container::const_iterator ft, fEnd = mesh.faces().end();
 
+		for (ft = mesh.faces().begin(); ft != fEnd; ++ft) {
 			int v0, v1, v2;
-			mesh->faceVertices(index, v0, v1, v2);
+			mesh.faceVertices(ft.index(), v0, v1, v2);
 
-			TTextureVertex const& p0 = vertices[v0];
-			TTextureVertex const& p1 = vertices[v1];
-			TTextureVertex const& p2 = vertices[v2];
+			const TTextureVertex &p0 = vertices[v0];
+			const TTextureVertex &p1 = vertices[v1];
+			const TTextureVertex &p2 = vertices[v2];
 
-			colorFunction.faceColor(index, m);
+			colorFunction.faceColor(ft.index(), m);
 
 			colorFunction.vertexColor(v0, m), glVertex2d(p0.P().x, p0.P().y);
 			colorFunction.vertexColor(v1, m), glVertex2d(p1.P().x, p1.P().y);
@@ -101,33 +98,39 @@ inline void tglDrawFaces(const TMeshImage &meshImage, const PlasticDeformerDataG
 {
 	glBegin(GL_TRIANGLES);
 
+	// Draw faces according to the group's sorted faces list
+	typedef std::vector<std::pair<int, int>> SortedFacesVector;
+
+	const SortedFacesVector &sortedFaces = group->m_sortedFaces;
 	const std::vector<TTextureMeshP> &meshes = meshImage.meshes();
 
-	// Draw faces according to the group's sorted faces list
-	// Draw each face individually. Change tile and mesh data only if they change
 	int m = -1;
-	for (auto const& sft : group->m_sortedFaces) {
-		TTextureMesh const* mesh = nullptr;
-		double const* dstCoords = nullptr;
+	const TTextureMesh *mesh;
+	const double *dstCoords;
+
+	int v0, v1, v2;
+
+	// Draw each face individually. Change tile and mesh data only if they change
+	SortedFacesVector::const_iterator sft, sfEnd(sortedFaces.end());
+	for (sft = sortedFaces.begin(); sft != sfEnd; ++sft) {
+		int f = sft->first, m_ = sft->second;
+
+		if (m != m_) {
+			m = m_;
 
-		if (m != sft.second) {
-			m = sft.second;
 			mesh = meshes[m].getPointer();
 			dstCoords = group->m_datas[m].m_output.get();
 		}
 
-		int v0, v1, v2;
-		mesh->faceVertices(sft.first, v0, v1, v2);
+		mesh->faceVertices(f, v0, v1, v2);
 
-		double const * const d0 = dstCoords + (v0 << 1);
-		double const * const d1 = dstCoords + (v1 << 1);
-		double const * const d2 = dstCoords + (v2 << 1);
+		const double *d0 = dstCoords + (v0 << 1), *d1 = dstCoords + (v1 << 1), *d2 = dstCoords + (v2 << 1);
 
-		colorFunction.faceColor(sft.first, m);
+		colorFunction.faceColor(f, m);
 
-		colorFunction.vertexColor(v0, m), glVertex2d(d0[0], d0[1]);
-		colorFunction.vertexColor(v1, m), glVertex2d(d1[0], d1[1]);
-		colorFunction.vertexColor(v2, m), glVertex2d(d2[0], d2[1]);
+		colorFunction.vertexColor(v0, m), glVertex2d(*d0, *(d0 + 1));
+		colorFunction.vertexColor(v1, m), glVertex2d(*d1, *(d1 + 1));
+		colorFunction.vertexColor(v2, m), glVertex2d(*d2, *(d2 + 1));
 	}
 
 	glEnd();
@@ -319,135 +322,189 @@ void tglDraw(const TMeshImage &meshImage,
 			 const DrawableTextureData &texData, const TAffine &meshToTexAff,
 			 const PlasticDeformerDataGroup &group)
 {
-#ifdef _WIN32
-	typedef void (*PFNGLBLENDFUNCSEPARATEPROC)(GLenum, GLenum, GLenum, GLenum);
-	static PFNGLBLENDFUNCSEPARATEPROC const glBlendFuncSeparate =
-		reinterpret_cast<PFNGLBLENDFUNCSEPARATEPROC>(::wglGetProcAddress("glBlendFuncSeparate"));
-#endif
+	typedef MeshTexturizer::TextureData::TileData TileData;
 
 	// Prepare OpenGL
 	glPushAttrib(GL_COLOR_BUFFER_BIT | GL_LINE_BIT | GL_HINT_BIT); // Preserve original status bits
 
 	glEnable(GL_BLEND);
-	glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
 	glEnable(GL_LINE_SMOOTH);
 	glLineWidth(1.0f);
 
 	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
 
-	glBlendFuncSeparate(
-		GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA,
-		GL_ONE      , GL_ONE_MINUS_SRC_ALPHA);
+	// Prepare variables
+	const std::vector<TTextureMeshP> &meshes = meshImage.meshes();
+	const TTextureMesh *mesh;
+
+	typedef std::vector<std::pair<int, int>> SortedFacesVector;
+	const SortedFacesVector &sortedFaces = group.m_sortedFaces;
+
+	const MeshTexturizer::TextureData *td = texData.m_textureData;
+	int t, tCount = td->m_tileDatas.size();
+
+	GLuint texId = -1;
+	int m = -1;
+	const double *dstCoords;
 
-	auto const& tiles = texData.m_textureData->m_tileDatas;
+	int v0, v1, v2;
+	int e1ovi, e2ovi; // Edge X's Other Vertex Index (see below)
 
 	// Prepare each tile's affine
-	std::unique_ptr<TAffine[]> tileAff(new TAffine[tiles.size()]);
-	{
-		std::size_t i = 0;
-		for (auto const& tile : tiles) {
-			TRectD const &rect = tile.m_tileGeometry;
-			TScale const scale(
-				1.0 / (rect.x1 - rect.x0),
-				1.0 / (rect.y1 - rect.y0));
-			TTranslation const translate(-rect.x0, -rect.y0);
-			tileAff[i] = scale * translate * meshToTexAff;
-		}
+	std::vector<TAffine> tileAff(tCount);
+	for (t = 0; t != tCount; ++t) {
+		const TileData &tileData = td->m_tileDatas[t];
+		const TRectD &tileRect = tileData.m_tileGeometry;
+
+		tileAff[t] = TScale(1.0 / (tileRect.x1 - tileRect.x0), 1.0 / (tileRect.y1 - tileRect.y0)) *
+					 TTranslation(-tileRect.x0, -tileRect.y0) *
+					 meshToTexAff;
 	}
 
 	// Draw each face individually, according to the group's sorted faces list.
 	// Change tile and mesh data only if they change - improves performance
-	int m = -1;
-	TTextureMesh const * mesh = nullptr;
-	double const * dstCoords = nullptr;
-	GLuint texId = -1;
-	for (auto const& sft : group.m_sortedFaces) {
-		if (m != sft.second) {
+
+	SortedFacesVector::const_iterator sft, sfEnd(sortedFaces.end());
+	for (sft = sortedFaces.begin(); sft != sfEnd; ++sft) {
+		int f = sft->first, m_ = sft->second;
+
+		if (m != m_) {
 			// Change mesh if different from current
-			m = sft.second;
-			mesh = meshImage.meshes()[m].getPointer();
+			m = m_;
+
+			mesh = meshes[m].getPointer();
 			dstCoords = group.m_datas[m].m_output.get();
 		}
 
 		// Draw each face
-		TTextureMesh::face_type const& fc = mesh->face(sft.first);
-		TTextureMesh::edge_type const& ed0 = mesh->edge(fc.edge(0));
-		TTextureMesh::edge_type const& ed1 = mesh->edge(fc.edge(1));
-		TTextureMesh::edge_type const& ed2 = mesh->edge(fc.edge(2));
-
-		int const v0 = ed0.vertex(0);
-		int const v1 = ed0.vertex(1);
-		int const v2 = ed1.vertex((ed1.vertex(0) == v0) | (ed1.vertex(0) == v1));
-
-		// Edge X's Other Vertex Index (see below)
-		int const f = (ed1.vertex(0) == v1) | (ed1.vertex(1) == v1); // ed1 and ed2 will refer to vertexes
-		int const g = 1 - f;									                       // with index 2 and these.
-
-		TPointD const& p0 = mesh->vertex(v0).P();
-		TPointD const& p1 = mesh->vertex(v1).P();
-		TPointD const& p2 = mesh->vertex(v2).P();
-
-		// Draw face against tile
-		std::size_t i = 0;
-		for (auto const& tileData : tiles) {
+		const TTextureMesh::face_type &fc = mesh->face(f);
+
+		const TTextureMesh::edge_type &ed0 = mesh->edge(fc.edge(0)),
+									  &ed1 = mesh->edge(fc.edge(1)),
+									  &ed2 = mesh->edge(fc.edge(2));
+
+		{
+			v0 = ed0.vertex(0);
+			v1 = ed0.vertex(1);
+			v2 = ed1.vertex((ed1.vertex(0) == v0) | (ed1.vertex(0) == v1));
+
+			e1ovi = (ed1.vertex(0) == v1) | (ed1.vertex(1) == v1); // ed1 and ed2 will refer to vertexes
+			e2ovi = 1 - e1ovi;									   // with index 2 and these.
+		}
+
+		const TPointD &p0 = mesh->vertex(v0).P(), &p1 = mesh->vertex(v1).P(), &p2 = mesh->vertex(v2).P();
+
+		for (t = 0; t != tCount; ++t) {
+			// Draw face against tile
+			const TileData &tileData = td->m_tileDatas[t];
+
 			// Map each face vertex to tile coordinates
-			std::array<TPointD, 3> const s = {
-				tileAff[i] * p0,
-				tileAff[i] * p1,
-				tileAff[i] * p2,
-			};
-			++i;
+			TPointD s[3] = {tileAff[t] * p0, tileAff[t] * p1, tileAff[t] * p2};
 
 			// Test the face bbox - tile intersection
-			if ( (tmin(s[0].x, s[1].x, s[2].x) > 1.0)
-				|| (tmin(s[0].y, s[1].y, s[2].y) > 1.0)
-				|| (tmax(s[0].x, s[1].x, s[2].x) < 0.0)
-				|| (tmax(s[0].y, s[1].y, s[2].y) < 0.0)) {
+			if (tmin(s[0].x, s[1].x, s[2].x) > 1.0 ||
+				tmin(s[0].y, s[1].y, s[2].y) > 1.0 ||
+				tmax(s[0].x, s[1].x, s[2].x) < 0.0 ||
+				tmax(s[0].y, s[1].y, s[2].y) < 0.0)
 				continue;
-			}
 
 			// If the tile has changed, interrupt the glBegin/glEnd block and bind the
 			// OpenGL texture corresponding to the new tile
-			if (texId != tileData.m_textureId) {
+			if (tileData.m_textureId != texId) {
 				texId = tileData.m_textureId;
 
-				// This must be OUTSIDE a glBegin/glEnd block
-				glBindTexture(GL_TEXTURE_2D, texId);
+				glBindTexture(GL_TEXTURE_2D, tileData.m_textureId); // This must be OUTSIDE a glBegin/glEnd block
 			}
 
-			std::array<double const *, 3> const d = {
-				dstCoords + (v0 << 1),
-				dstCoords + (v1 << 1),
-				dstCoords + (v2 << 1),
-			};
+			const double *d[3] = {dstCoords + (v0 << 1),
+								  dstCoords + (v1 << 1),
+								  dstCoords + (v2 << 1)};
+
+			/*
+        Now, draw primitives. A note about pixel arithmetic, here.
+        
+        Since line antialiasing in OpenGL just manipulates output fragments' alpha components,
+        we must require that the input texture is NONPREMULTIPLIED.
+
+        Furthermore, this function does not rely on the assumption that the output alpha component
+        is discarded (as it happens when drawing on screen). This means that just using a simple
+        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) is not an option, since this way THE INPUT
+        SRC ALPHA GETS MULTIPLIED BY ITSELF - see glBlendFunc's docs - and that shows.
+
+        The solution is to separate the rendering of RGB and M components - the formers use
+        GL_SRC_ALPHA, while the latter uses GL_ONE. The result is a PREMULTIPLIED image.
+      */
 
 			// First, draw antialiased face edges on the mesh border.
+			bool drawEd0 = (ed0.facesCount() < 2),
+				 drawEd1 = (ed1.facesCount() < 2),
+				 drawEd2 = (ed2.facesCount() < 2);
+
+			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+			glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+
+			glBegin(GL_LINES);
+			{
+				if (drawEd0) {
+					glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
+					glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
+				}
+
+				if (drawEd1) {
+					glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1));
+					glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
+				}
+
+				if (drawEd2) {
+					glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1));
+					glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
+				}
+			}
+			glEnd();
+
+			glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+			glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+
 			glBegin(GL_LINES);
 			{
-				if (ed0.facesCount() < 2) {
-					glTexCoord2d(s[0].x, s[0].y), glVertex2d(d[0][0], d[0][1]);
-					glTexCoord2d(s[1].x, s[1].y), glVertex2d(d[1][0], d[1][1]);
+				if (drawEd0) {
+					glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
+					glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
 				}
 
-				if (ed1.facesCount() < 2) {
-					glTexCoord2d(s[f].x, s[f].y), glVertex2d(d[f][0], d[f][1]);
-					glTexCoord2d(s[2].x, s[2].y), glVertex2d(d[2][0], d[2][1]);
+				if (drawEd1) {
+					glTexCoord2d(s[e1ovi].x, s[e1ovi].y), glVertex2d(*d[e1ovi], *(d[e1ovi] + 1));
+					glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
 				}
 
-				if (ed2.facesCount() < 2) {
-					glTexCoord2d(s[g].x, s[g].y), glVertex2d(d[g][0], d[g][1]);
-					glTexCoord2d(s[2].x, s[2].y), glVertex2d(d[2][0], d[2][1]);
+				if (drawEd2) {
+					glTexCoord2d(s[e2ovi].x, s[e2ovi].y), glVertex2d(*d[e2ovi], *(d[e2ovi] + 1));
+					glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
 				}
 			}
 			glEnd();
 
 			// Finally, draw the face
+			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+			glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_FALSE);
+
+			glBegin(GL_TRIANGLES);
+			{
+				glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
+				glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
+				glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
+			}
+			glEnd();
+
+			glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+			glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE);
+
 			glBegin(GL_TRIANGLES);
 			{
-				glTexCoord2d(s[0].x, s[0].y), glVertex2d(d[0][0], d[0][1]);
-				glTexCoord2d(s[1].x, s[1].y), glVertex2d(d[1][0], d[1][1]);
-				glTexCoord2d(s[2].x, s[2].y), glVertex2d(d[2][0], d[2][1]);
+				glTexCoord2d(s[0].x, s[0].y), glVertex2d(*d[0], *(d[0] + 1));
+				glTexCoord2d(s[1].x, s[1].y), glVertex2d(*d[1], *(d[1] + 1));
+				glTexCoord2d(s[2].x, s[2].y), glVertex2d(*d[2], *(d[2] + 1));
 			}
 			glEnd();
 		}
diff --git a/toonz/sources/toonzlib/imagebuilders.cpp b/toonz/sources/toonzlib/imagebuilders.cpp
index e56994f..508cd6d 100644
--- a/toonz/sources/toonzlib/imagebuilders.cpp
+++ b/toonz/sources/toonzlib/imagebuilders.cpp
@@ -40,8 +40,6 @@
 
 extern TOfflineGL *currentOfflineGL;
 
-//-----------------------------------------------------------------------------
-
 //***************************************************************************************
 //    ImageLoader  implementation
 //***************************************************************************************
diff --git a/toonz/sources/toonzlib/textureutils.cpp b/toonz/sources/toonzlib/textureutils.cpp
index 1d4affe..9a84030 100644
--- a/toonz/sources/toonzlib/textureutils.cpp
+++ b/toonz/sources/toonzlib/textureutils.cpp
@@ -29,6 +29,7 @@
 
 namespace
 {
+
 TRasterImageP convert32(const TImageP &img)
 {
 	struct locals {
@@ -95,10 +96,12 @@ TRasterImageP getTexture(const TXshSimpleLevel *sl, const TFrameId &fid, int sub
 	}
 
 	// Vector case
-	std::string const id = sl->getImageId(fid) + "_rasterized";
+	std::string id = sl->getImageId(fid) + "_rasterized";
 
 	ImageLoader::BuildExtData extData(sl, fid);
-	return ImageManager::instance()->getImage(id, ImageManager::dontPutInCache, &extData);
+	TRasterImageP ri(ImageManager::instance()->getImage(id, ImageManager::dontPutInCache, &extData));
+
+	return ri;
 }
 
 } // namespace
@@ -127,10 +130,10 @@ DrawableTextureDataP texture_utils::getTextureData(
 	TRaster32P ras(ri->getRaster());
 	assert(ras);
 
-	TRectD const geom
-		= TScale(ri->getSubsampling())
-		* TTranslation(convert(ri->getOffset()) - ras->getCenterD())
-		* TRectD(0, 0, ras->getLx(), ras->getLy());
+	TRectD geom(0, 0, ras->getLx(), ras->getLy());
+	geom = TScale(ri->getSubsampling()) *
+		   TTranslation(convert(ri->getOffset()) - ras->getCenterD()) *
+		   geom;
 
 	return TTexturesStorage::instance()->loadTexture(texId, ras, geom);
 }
diff --git a/toonz/sources/toonzqt/icongenerator.cpp b/toonz/sources/toonzqt/icongenerator.cpp
index e27f9e4..ea21027 100644
--- a/toonz/sources/toonzqt/icongenerator.cpp
+++ b/toonz/sources/toonzqt/icongenerator.cpp
@@ -199,13 +199,16 @@ void makeChessBackground(const TRaster32P &ras)
 
 namespace
 {
-TRaster32P convertToIcon(TVectorImageP vimage, int frame,
-	TDimension const& iconSize, IconGenerator::Settings const& settings)
+TRaster32P convertToIcon(
+	TVectorImageP vimage,
+	int frame,
+	const TDimension &iconSize,
+	const IconGenerator::Settings &settings)
 {
 	if (!vimage)
 		return TRaster32P();
 
-	std::unique_ptr<TPalette> plt(vimage->getPalette()->clone());
+	TPalette *plt = vimage->getPalette()->clone();
 	if (!plt)
 		return TRaster32P();
 	plt->setFrame(frame);
@@ -234,31 +237,42 @@ TRaster32P convertToIcon(TVectorImageP vimage, int frame,
 	TAffine aff = TScale(sc).place(imageCenter, iconCenter);
 
 	// RenderData
-	TVectorRenderData rd(aff, TRect(iconSize), plt.get(), 0, true);
+	TVectorRenderData rd(
+		aff,
+		TRect(iconSize),
+		plt,
+		0, true);
+
 	rd.m_tcheckEnabled = settings.m_transparencyCheck;
 	rd.m_blackBgEnabled = settings.m_blackBgCheck;
 	rd.m_drawRegions = !settings.m_inksOnly;
-	rd.m_inkCheckEnabled = (settings.m_inkIndex != -1);
-	rd.m_paintCheckEnabled = (settings.m_paintIndex != -1);
+	rd.m_inkCheckEnabled = settings.m_inkIndex != -1;
+	rd.m_paintCheckEnabled = settings.m_paintIndex != -1;
 	rd.m_colorCheckIndex = rd.m_inkCheckEnabled ? settings.m_inkIndex : settings.m_paintIndex;
 	rd.m_isIcon = true;
 
 	// disegno l'immagine
 	glContext->makeCurrent();
-	glContext->clear(rd.m_blackBgEnabled ? TPixel32::Black : TPixel32::White);
+	glContext->clear(rd.m_blackBgEnabled ? TPixel::Black : TPixel32::White);
 	glContext->draw(vimage, rd);
 
 	TRaster32P ras(iconSize);
 	glContext->getRaster(ras);
+
 	glContext->doneCurrent();
 
+	delete plt;
+
 	return ras;
 }
 
 //-------------------------------------------------------------------------
 
-TRaster32P convertToIcon(TToonzImageP timage, int frame,
-	TDimension const& iconSize, IconGenerator::Settings const& settings)
+TRaster32P convertToIcon(
+	TToonzImageP timage,
+	int frame,
+	const TDimension &iconSize,
+	const IconGenerator::Settings &settings)
 {
 	if (!timage)
 		return TRaster32P();