1 
2 
3 #include "toonz/textureutils.h"
4 
5 // TnzLib includes
6 #include "toonz/txshleveltypes.h"
7 #include "toonz/txshsimplelevel.h"
8 #include "toonz/txshchildlevel.h"
9 #include "toonz/txsheet.h"
10 #include "toonz/tstageobjecttree.h"
11 #include "toonz/txshcell.h"
12 #include "toonz/tstageobject.h"
13 #include "toonz/stage.h"
14 #include "toonz/toonzscene.h"
15 #include "toonz/imagemanager.h"
16 #include "imagebuilders.h"
17 
18 // TnzCore includes
19 #include "tpalette.h"
20 #include "tconvert.h"
21 #include "ttoonzimage.h"
22 #include "trop.h"
23 #include "tropcm.h"
24 #include "tgl.h"
25 
26 //********************************************************************************************
27 //    TXshSimpleLevel Texture Utilities  locals
28 //********************************************************************************************
29 
30 namespace {
31 
convert32(const TImageP & img)32 TRasterImageP convert32(const TImageP &img) {
33   struct locals {
34     static TRasterImageP depremultiplied(const TRasterImageP &ri) {
35       assert(ri->getRaster());
36 
37       TRop::depremultiply(ri->getRaster());
38       return ri;
39     }
40   };  // locals
41 
42   if (TRasterImageP ri = img) {
43     TRasterP ras(ri->getRaster());
44 
45     TRaster32P ras32;
46     {
47       if (TRaster32P(ras))
48         ras32 = ras->clone();
49       else {
50         ras32 = TRaster32P(ras->getSize());
51         TRop::convert(ras32, ras);
52       }
53     }
54 
55     TPointD dpi;
56     ri->getDpi(dpi.x, dpi.y);
57 
58     TRasterImageP ri32(ras32);
59     ri32->setDpi(dpi.x, dpi.y);
60     ri32->setSubsampling(ri->getSubsampling());
61     ri32->setOffset(ri->getOffset());
62 
63     return locals::depremultiplied(ri32);
64   }
65 
66   if (TToonzImageP ti = img) {
67     TRasterCM32P rasCM32(ti->getRaster());
68 
69     TRaster32P ras32(rasCM32->getSize());
70     TRop::convert(ras32, rasCM32, ti->getPalette());
71 
72     TPointD dpi;
73     ti->getDpi(dpi.x, dpi.y);
74 
75     TRasterImageP ri32(ras32);
76     ri32->setDpi(dpi.x, dpi.y);
77     ri32->setSubsampling(ti->getSubsampling());
78     ri32->setOffset(ti->getOffset());
79 
80     return locals::depremultiplied(ri32);
81   }
82 
83   return TRasterImageP();
84 }
85 
86 //-----------------------------------------------------------------------------
87 
getTexture(const TXshSimpleLevel * sl,const TFrameId & fid,int subsampling)88 TRasterImageP getTexture(const TXshSimpleLevel *sl, const TFrameId &fid,
89                          int subsampling) {
90   if (sl->getType() != PLI_XSHLEVEL) {
91     TImageP texImg =
92         sl->getFrame(fid, ImageManager::dontPutInCache, subsampling);
93     return convert32(texImg);
94   }
95 
96   // Vector case
97   std::string id = sl->getImageId(fid) + "_rasterized";
98 
99   ImageLoader::BuildExtData extData(sl, fid);
100   TRasterImageP ri(ImageManager::instance()->getImage(
101       id, ImageManager::dontPutInCache, &extData));
102 
103   return convert32(ri);
104 }
105 
106 }  // namespace
107 
108 //********************************************************************************************
109 //    TXshSimpleLevel Texture Utilities  implementation
110 //********************************************************************************************
111 
getTextureData(const TXshSimpleLevel * sl,const TFrameId & fid,int subsampling)112 DrawableTextureDataP texture_utils::getTextureData(const TXshSimpleLevel *sl,
113                                                    const TFrameId &fid,
114                                                    int subsampling) {
115   const std::string &texId = sl->getImageId(fid);
116 
117   // Now, we must associate a texture
118   DrawableTextureDataP data(
119       TTexturesStorage::instance()->getTextureData(texId));
120   if (data) return data;
121 
122   // There was no associated texture. We must bind the texture and repeat
123 
124   // First, retrieve the image to be used as texture
125   TRasterImageP ri(::getTexture(sl, fid, subsampling));
126   if (!ri) return DrawableTextureDataP();
127 
128   TRaster32P ras(ri->getRaster());
129   assert(ras);
130 
131   TRectD geom(0, 0, ras->getLx(), ras->getLy());
132   geom = TScale(ri->getSubsampling()) *
133          TTranslation(convert(ri->getOffset()) - ras->getCenterD()) * geom;
134 
135   return TTexturesStorage::instance()->loadTexture(texId, ras, geom);
136 }
137 
138 //-----------------------------------------------------------------------------
139 
invalidateTexture(const TXshSimpleLevel * sl,const TFrameId & fid)140 void texture_utils::invalidateTexture(const TXshSimpleLevel *sl,
141                                       const TFrameId &fid) {
142   const std::string &texId = sl->getImageId(fid);
143   TTexturesStorage::instance()->unloadTexture(texId);
144 }
145 
146 //-----------------------------------------------------------------------------
147 
invalidateTextures(const TXshSimpleLevel * sl)148 void texture_utils::invalidateTextures(const TXshSimpleLevel *sl) {
149   int f, fCount = sl->getFrameCount();
150 
151   for (f = 0; f != fCount; ++f) invalidateTexture(sl, sl->getFrameId(f));
152 }
153 
154 //********************************************************************************************
155 //    TXsheet Texture Utilities  locals
156 //********************************************************************************************
157 
158 namespace {
159 
getImageId(const TXsheet * xsh,int frame)160 std::string getImageId(const TXsheet *xsh, int frame) {
161   return "X" + std::to_string(xsh->id()) + "_" + std::to_string(frame);
162 }
163 
164 }  // namespace
165 
166 //********************************************************************************************
167 //    TXsheet Texture Utilities  implementation
168 //********************************************************************************************
169 
getTextureData(const TXsheet * xsh,int frame)170 DrawableTextureDataP texture_utils::getTextureData(const TXsheet *xsh,
171                                                    int frame) {
172   // Check if an xsheet texture already exists
173   const std::string &texId = ::getImageId(xsh, frame);
174 
175   DrawableTextureDataP data(
176       TTexturesStorage::instance()->getTextureData(texId));
177   if (data) return data;
178 
179   // No available texture - we must build and load it
180   TRaster32P tex(
181       1024,
182       1024);  // Fixed texture size. It's the same that currently happens with
183               // vector images' textures - and justified since this is camstand
184   // mode, and besides we want to make sure that textures are limited.
185 
186   // Retrieve the sub-xsheet bbox (world coordinates of the sub-xsheet)
187   TRectD bbox(xsh->getBBox(frame));
188 
189   // Since xsh represents a sub-xsheet, its camera affine must be applied
190   const TAffine &cameraAff =
191       xsh->getPlacement(xsh->getStageObjectTree()->getCurrentCameraId(), frame);
192   bbox = (cameraAff.inv() * bbox).enlarge(1.0);
193 
194 // Render the xsheet on the specified bbox
195 #ifdef MACOSX
196   xsh->getScene()->renderFrame(tex, frame, xsh, bbox, TAffine());
197 #else
198   // The call below will change context (I know, it's a shame :( )
199   TGlContext currentContext = tglGetCurrentContext();
200   {
201     tglDoneCurrent(currentContext);
202     xsh->getScene()->renderFrame(tex, frame, xsh, bbox, TAffine());
203     tglMakeCurrent(currentContext);
204   }
205 #endif
206 
207   TRop::depremultiply(tex);  // Stored textures are rendered nonpremultiplied
208 
209   // Store the texture for future retrieval
210   return TTexturesStorage::instance()->loadTexture(texId, tex, bbox);
211 }
212 
213 //-----------------------------------------------------------------------------
214 
invalidateTexture(const TXsheet * xsh,int frame)215 void texture_utils::invalidateTexture(const TXsheet *xsh, int frame) {
216   const std::string &texId = ::getImageId(xsh, frame);
217   TTexturesStorage::instance()->unloadTexture(texId);
218 }
219 
220 //-----------------------------------------------------------------------------
221 
invalidateTextures(const TXsheet * xsh)222 void texture_utils::invalidateTextures(const TXsheet *xsh) {
223   int f, fCount = xsh->getFrameCount();
224   for (f = 0; f != fCount; ++f) invalidateTexture(xsh, f);
225 }
226