c6db5d392af420a6400e8365759a37413a78cedd
[platform/upstream/doxygen.git] / src / resourcemgr.cpp
1 /******************************************************************************
2  *
3  * Copyright (C) 1997-2015 by Dimitri van Heesch.
4  *
5  * Permission to use, copy, modify, and distribute this software and its
6  * documentation under the terms of the GNU General Public License is hereby
7  * granted. No representations are made about the suitability of this software
8  * for any purpose. It is provided "as is" without express or implied warranty.
9  * See the GNU General Public License for more details.
10  *
11  * Documents produced by Doxygen are derivative works derived from the
12  * input used in their production; they are not affected by this license.
13  *
14  */
15
16 #include <map>
17 #include <string.h>
18 #include <fstream>
19
20 #include "resourcemgr.h"
21 #include "util.h"
22 #include "version.h"
23 #include "message.h"
24 #include "config.h"
25
26 class ResourceMgr::Private
27 {
28   public:
29     std::map<std::string,Resource> resources;
30 };
31
32 ResourceMgr &ResourceMgr::instance()
33 {
34   static ResourceMgr theInstance;
35   return theInstance;
36 }
37
38 ResourceMgr::ResourceMgr() : p(std::make_unique<Private>())
39 {
40 }
41
42 ResourceMgr::~ResourceMgr()
43 {
44 }
45
46 void ResourceMgr::registerResources(std::initializer_list<Resource> resources)
47 {
48   for (auto &res : resources)
49   {
50     p->resources.insert({res.name,res});
51   }
52 }
53
54 bool ResourceMgr::writeCategory(const QCString &categoryName,const QCString &targetDir) const
55 {
56   for (auto &kv : p->resources)
57   {
58     Resource &res = kv.second;
59     if (res.category==categoryName)
60     {
61       std::string pathName = targetDir.str()+"/"+res.name;
62       std::ofstream f(pathName,std::ofstream::out | std::ofstream::binary);
63       bool ok=false;
64       if (f.is_open())
65       {
66         f.write(reinterpret_cast<const char *>(res.data),res.size);
67         ok = !f.fail();
68       }
69       if (!ok)
70       {
71         err("Failed to write resource '%s' to directory '%s'\n",res.name,qPrint(targetDir));
72         return FALSE;
73       }
74     }
75   }
76   return TRUE;
77 }
78
79 bool ResourceMgr::copyResourceAs(const QCString &name,const QCString &targetDir,const QCString &targetName,bool append) const
80 {
81   std::string pathName = targetDir.str()+"/"+targetName.str();
82   std::ios_base::openmode mode = std::ofstream::out | std::ofstream::binary;
83   if (append) mode |= std::ofstream::app;
84   const Resource *res = get(name);
85   if (res)
86   {
87     switch (res->type)
88     {
89       case Resource::Verbatim:
90         {
91           std::ofstream f(pathName,mode);
92           bool ok=false;
93           if (f.is_open())
94           {
95             f.write(reinterpret_cast<const char *>(res->data),res->size);
96             ok = !f.fail();
97           }
98           if (ok)
99           {
100             return TRUE;
101           }
102         }
103         break;
104       case Resource::Luminance:
105         {
106           QCString n = name;
107           n = n.left(n.length()-4)+".png"; // replace .lum by .png
108           const uchar *data = res->data;
109           ushort width   = (data[0]<<8)+data[1];
110           ushort height  = (data[2]<<8)+data[3];
111           ColoredImgDataItem images[2];
112           images[0].name    = n.data();
113           images[0].width   = width;
114           images[0].height  = height;
115           images[0].content = &data[4];
116           images[0].alpha   = 0;
117           images[1].name    = 0; // terminator
118           writeColoredImgData(targetDir,images);
119           return TRUE;
120         }
121         break;
122       case Resource::LumAlpha:
123         {
124           QCString n = name;
125           n = n.left(n.length()-5)+".png"; // replace .luma by .png
126           const uchar *data = res->data;
127           ushort width   = (data[0]<<8)+data[1];
128           ushort height  = (data[2]<<8)+data[3];
129           ColoredImgDataItem images[2];
130           images[0].name    = n.data();
131           images[0].width   = width;
132           images[0].height  = height;
133           images[0].content = &data[4];
134           images[0].alpha   = &data[4+width*height];
135           images[1].name    = 0; // terminator
136           writeColoredImgData(targetDir,images);
137           return TRUE;
138         }
139         break;
140       case Resource::CSS:
141         {
142           std::ofstream t(pathName,mode);
143           if (t.is_open())
144           {
145             QCString buf(res->size+1);
146             memcpy(buf.rawData(),res->data,res->size);
147             buf = replaceColorMarkers(buf);
148             if (name=="navtree.css")
149             {
150               t << substitute(buf,"$width",QCString().setNum(Config_getInt(TREEVIEW_WIDTH))+"px");
151             }
152             else
153             {
154               t << substitute(buf,"$doxygenversion",getDoxygenVersion());
155             }
156             return TRUE;
157           }
158         }
159         break;
160       case Resource::SVG:
161         {
162           std::ofstream t(pathName,mode);
163           if (t.is_open())
164           {
165             QCString buf(res->size+1);
166             memcpy(buf.rawData(),res->data,res->size);
167             t << replaceColorMarkers(buf);
168             return TRUE;
169           }
170         }
171     }
172   }
173   else
174   {
175     err("requested resource '%s' not compiled in!\n",qPrint(name));
176   }
177   return FALSE;
178 }
179
180 bool ResourceMgr::copyResource(const QCString &name,const QCString &targetDir) const
181 {
182   return copyResourceAs(name,targetDir,name);
183 }
184
185 const Resource *ResourceMgr::get(const QCString &name) const
186 {
187   auto it = p->resources.find(name.str());
188   if (it!=p->resources.end()) return &it->second;
189   return 0;
190 }
191
192 QCString ResourceMgr::getAsString(const QCString &name) const
193 {
194   const Resource *res = get(name);
195   if (res)
196   {
197     QCString result(res->size+1);
198     memcpy(result.rawData(),res->data,res->size);
199     return result;
200   }
201   else
202   {
203     return QCString();
204   }
205 }
206