Add post processor
[platform/core/uifw/dali-toolkit.git] / dali-toolkit / internal / visuals / visual-url.cpp
1 /*
2  * Copyright (c) 2021 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 // CLASS HEADER
18 #include <dali-toolkit/internal/visuals/visual-url.h>
19
20 // EXTERNAL HEADERS
21 #include <cstring> // for toupper()
22
23 namespace Dali
24 {
25 namespace Toolkit
26 {
27 namespace Internal
28 {
29 namespace
30 {
31 VisualUrl::ProtocolType ResolveLocation(const std::string& url)
32 {
33   const char*    urlCStr = url.c_str();
34   const uint32_t length  = url.size();
35   if((length > 7) && urlCStr[5] == ':' && urlCStr[6] == '/' && urlCStr[7] == '/')
36   {
37     // https://
38     if(('h' == tolower(urlCStr[0])) &&
39        ('t' == tolower(urlCStr[1])) &&
40        ('t' == tolower(urlCStr[2])) &&
41        ('p' == tolower(urlCStr[3])) &&
42        ('s' == tolower(urlCStr[4])))
43     {
44       return VisualUrl::REMOTE;
45     }
46   }
47   else if((length > 6) && urlCStr[4] == ':' && urlCStr[5] == '/' && urlCStr[6] == '/')
48   {
49     // http:// or dali://
50     const char hOrd = tolower(urlCStr[0]);
51     const char tOra = tolower(urlCStr[1]);
52     const char tOrl = tolower(urlCStr[2]);
53     const char pOri = tolower(urlCStr[3]);
54     if(('h' == hOrd) &&
55        ('t' == tOra) &&
56        ('t' == tOrl) &&
57        ('p' == pOri))
58     {
59       return VisualUrl::REMOTE;
60     }
61     if(('d' == hOrd) &&
62        ('a' == tOra) &&
63        ('l' == tOrl) &&
64        ('i' == pOri))
65     {
66       return VisualUrl::TEXTURE;
67     }
68   }
69   else if((length > 5) && urlCStr[3] == ':' && urlCStr[4] == '/' && urlCStr[5] == '/')
70   {
71     // ftp:// or ssh://
72     const char fOrS = tolower(urlCStr[0]);
73     if(('f' == fOrS) || ('s' == fOrS))
74     {
75       const char tOrs = tolower(urlCStr[1]);
76       if(('t' == tOrs) || ('s' == tOrs))
77       {
78         const char pOrh = tolower(urlCStr[2]);
79         if(('p' == pOrh) || ('h' == pOrh))
80         {
81           return VisualUrl::REMOTE;
82         }
83       }
84     }
85   }
86   return VisualUrl::LOCAL;
87 }
88
89 VisualUrl::Type ResolveType(const std::string& url)
90 {
91   // if only one char in string, can only be regular image
92   const std::size_t count = url.size();
93   if(count > 0)
94   {
95     // parsing from the end for better chance of early outs
96     enum
97     {
98       SUFFIX,
99       HASH,
100       HASH_DOT
101     } state                = SUFFIX;
102     char         SVG[4]    = {'g', 'v', 's', '.'};
103     char         GIF[4]    = {'f', 'i', 'g', '.'};
104     char         WEBP[5]   = {'p', 'b', 'e', 'w', '.'};
105     char         JSON[5]   = {'n', 'o', 's', 'j', '.'};
106     unsigned int svgScore  = 0;
107     unsigned int gifScore  = 0;
108     unsigned int webpScore = 0;
109     unsigned int jsonScore = 0;
110     int          index     = count;
111     while(--index >= 0)
112     {
113       const char        currentChar   = tolower(url[index]);
114       const std::size_t offsetFromEnd = count - index - 1u;
115       if((offsetFromEnd < sizeof(SVG)) && (currentChar == SVG[offsetFromEnd]))
116       {
117         // early out if SVG as can't be used in N patch for now
118         if(++svgScore == sizeof(SVG))
119         {
120           return VisualUrl::SVG;
121         }
122       }
123       if((offsetFromEnd < sizeof(GIF)) && (currentChar == GIF[offsetFromEnd]))
124       {
125         // early out if GIF as can't be used in N patch for now
126         if(++gifScore == sizeof(GIF))
127         {
128           return VisualUrl::GIF;
129         }
130       }
131       if((offsetFromEnd < sizeof(WEBP)) && (currentChar == WEBP[offsetFromEnd]))
132       {
133         // early out if WEBP as can't be used in N patch for now
134         if(++webpScore == sizeof(WEBP))
135         {
136           return VisualUrl::WEBP;
137         }
138       }
139       if((offsetFromEnd < sizeof(JSON)) && (currentChar == JSON[offsetFromEnd]))
140       {
141         // early out if JSON as can't be used in N patch for now
142         if(++jsonScore == sizeof(JSON))
143         {
144           return VisualUrl::JSON;
145         }
146       }
147       switch(state)
148       {
149         case SUFFIX:
150         {
151           if('.' == currentChar)
152           {
153             state = HASH;
154           }
155           break;
156         }
157         case HASH:
158         {
159           if(('#' == currentChar) || ('9' == currentChar))
160           {
161             state = HASH_DOT;
162           }
163           else
164           {
165             // early out, not a valid N/9-patch URL
166             return VisualUrl::REGULAR_IMAGE;
167           }
168           break;
169         }
170         case HASH_DOT:
171         {
172           if('.' == currentChar)
173           {
174             return VisualUrl::N_PATCH;
175           }
176           else
177           {
178             // early out, not a valid N/9-patch URL
179             return VisualUrl::REGULAR_IMAGE;
180           }
181           break;
182         }
183       }
184     }
185   }
186   // if we got here it is a regular image
187   return VisualUrl::REGULAR_IMAGE;
188 }
189
190 } // namespace
191
192 VisualUrl::VisualUrl()
193 : mUrl(),
194   mType(VisualUrl::REGULAR_IMAGE),
195   mLocation(VisualUrl::LOCAL)
196 {
197 }
198
199 VisualUrl::VisualUrl(const std::string& url)
200 : mUrl(url),
201   mType(VisualUrl::REGULAR_IMAGE),
202   mLocation(VisualUrl::LOCAL)
203 {
204   if(!url.empty())
205   {
206     mLocation = ResolveLocation(url);
207     if(VisualUrl::TEXTURE != mLocation)
208     {
209       // TEXTURE location url doesn't need type resolving, REGULAR_IMAGE is fine
210       mType = ResolveType(url);
211     }
212   }
213 }
214
215 VisualUrl::VisualUrl(const VisualUrl& url)
216 : mUrl(url.mUrl),
217   mType(url.mType),
218   mLocation(url.mLocation)
219 {
220 }
221
222 VisualUrl& VisualUrl::operator=(const VisualUrl& url)
223 {
224   if(&url != this)
225   {
226     mUrl      = url.mUrl;
227     mType     = url.mType;
228     mLocation = url.mLocation;
229   }
230   return *this;
231 }
232
233 const std::string& VisualUrl::GetUrl() const
234 {
235   return mUrl;
236 }
237
238 VisualUrl::Type VisualUrl::GetType() const
239 {
240   return mType;
241 }
242
243 VisualUrl::ProtocolType VisualUrl::GetProtocolType() const
244 {
245   return mLocation;
246 }
247
248 bool VisualUrl::IsValid() const
249 {
250   return mUrl.size() > 0u;
251 }
252
253 bool VisualUrl::IsLocalResource() const
254 {
255   return mLocation == VisualUrl::LOCAL;
256 }
257
258 std::string VisualUrl::GetLocation() const
259 {
260   const auto location = mUrl.find("://");
261   if(std::string::npos != location)
262   {
263     return mUrl.substr(location + 3u); // 3 characters forwards from the start of ://
264   }
265   return mUrl;
266 }
267
268 std::string VisualUrl::CreateTextureUrl(const std::string& location)
269 {
270   return "dali://" + location;
271 }
272
273 } // namespace Internal
274
275 } // namespace Toolkit
276
277 } // namespace Dali