a6f4a5c08ffea17c281bd8ba8ee557bf2779d91c
[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 <cstdint>
19
20 #include "resourcemgr.h"
21 #include "util.h"
22 #include "version.h"
23 #include "message.h"
24 #include "config.h"
25 #include "portable.h"
26
27 class ResourceMgr::Private
28 {
29   public:
30     std::map<std::string,Resource> resources;
31 };
32
33 ResourceMgr &ResourceMgr::instance()
34 {
35   static ResourceMgr theInstance;
36   return theInstance;
37 }
38
39 ResourceMgr::ResourceMgr() : p(std::make_unique<Private>())
40 {
41 }
42
43 ResourceMgr::~ResourceMgr()
44 {
45 }
46
47 void ResourceMgr::registerResources(std::initializer_list<Resource> resources)
48 {
49   for (auto &res : resources)
50   {
51     p->resources.insert({res.name,res});
52   }
53 }
54
55 bool ResourceMgr::writeCategory(const QCString &categoryName,const QCString &targetDir) const
56 {
57   for (auto &[name,res] : p->resources)
58   {
59     if (res.category==categoryName)
60     {
61       QCString pathName = targetDir+"/"+res.name;
62       std::ofstream f = Portable::openOutputStream(pathName);
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   QCString pathName = targetDir+"/"+targetName;
82   const Resource *res = get(name);
83   if (res)
84   {
85     switch (res->type)
86     {
87       case Resource::Verbatim:
88         {
89           std::ofstream f = Portable::openOutputStream(pathName,append);
90           bool ok=false;
91           if (f.is_open())
92           {
93             f.write(reinterpret_cast<const char *>(res->data),res->size);
94             ok = !f.fail();
95           }
96           if (ok)
97           {
98             return TRUE;
99           }
100         }
101         break;
102       case Resource::Luminance:
103         {
104           QCString n = name;
105           n = n.left(n.length()-4)+".png"; // replace .lum by .png
106           const uint8_t *data = res->data;
107           uint16_t width   = (data[0]<<8)+data[1];
108           uint16_t height  = (data[2]<<8)+data[3];
109           ColoredImgDataItem images[2];
110           images[0].name    = n.data();
111           images[0].width   = width;
112           images[0].height  = height;
113           images[0].content = &data[4];
114           images[0].alpha   = 0;
115           images[1].name    = 0; // terminator
116           writeColoredImgData(targetDir,images);
117           return TRUE;
118         }
119         break;
120       case Resource::LumAlpha:
121         {
122           QCString n = name;
123           n = n.left(n.length()-5)+".png"; // replace .luma by .png
124           const uint8_t *data = res->data;
125           uint16_t width   = (data[0]<<8)+data[1];
126           uint16_t height  = (data[2]<<8)+data[3];
127           ColoredImgDataItem images[2];
128           images[0].name    = n.data();
129           images[0].width   = width;
130           images[0].height  = height;
131           images[0].content = &data[4];
132           images[0].alpha   = &data[4+width*height];
133           images[1].name    = 0; // terminator
134           writeColoredImgData(targetDir,images);
135           return TRUE;
136         }
137         break;
138       case Resource::CSS:
139         {
140           std::ofstream t = Portable::openOutputStream(pathName,append);
141           if (t.is_open())
142           {
143             QCString buf(res->size+1);
144             memcpy(buf.rawData(),res->data,res->size);
145             buf = replaceColorMarkers(buf);
146             if (name=="navtree.css")
147             {
148               t << substitute(buf,"$width",QCString().setNum(Config_getInt(TREEVIEW_WIDTH))+"px");
149             }
150             else
151             {
152               t << substitute(buf,"$doxygenversion",getDoxygenVersion());
153             }
154             return TRUE;
155           }
156         }
157         break;
158       case Resource::SVG:
159         {
160           std::ofstream t = Portable::openOutputStream(pathName,append);
161           if (t.is_open())
162           {
163             QCString buf(res->size+1);
164             memcpy(buf.rawData(),res->data,res->size);
165             t << replaceColorMarkers(buf);
166             return TRUE;
167           }
168         }
169     }
170   }
171   else
172   {
173     err("requested resource '%s' not compiled in!\n",qPrint(name));
174   }
175   return FALSE;
176 }
177
178 bool ResourceMgr::copyResource(const QCString &name,const QCString &targetDir) const
179 {
180   return copyResourceAs(name,targetDir,name);
181 }
182
183 const Resource *ResourceMgr::get(const QCString &name) const
184 {
185   auto it = p->resources.find(name.str());
186   if (it!=p->resources.end()) return &it->second;
187   return 0;
188 }
189
190 QCString ResourceMgr::getAsString(const QCString &name) const
191 {
192   const Resource *res = get(name);
193   if (res)
194   {
195     QCString result(res->size+1);
196     memcpy(result.rawData(),res->data,res->size);
197     return result;
198   }
199   else
200   {
201     return QCString();
202   }
203 }
204