image_xpm.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
  1. /*
  2. * File : image_xpm.c
  3. * This file is part of RT-Thread GUI Engine
  4. * COPYRIGHT (C) 2006 - 2017, RT-Thread Development Team
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along
  17. * with this program; if not, write to the Free Software Foundation, Inc.,
  18. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  19. *
  20. * Change Logs:
  21. * Date Author Notes
  22. * 2009-10-16 Bernard first version
  23. */
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include <rtgui/filerw.h>
  27. #include <rtgui/rtgui_system.h>
  28. #include <rtgui/image.h>
  29. #ifdef RTGUI_IMAGE_XPM
  30. #define XPM_MAGIC_LEN 9
  31. static rt_bool_t rtgui_image_xpm_check(struct rtgui_filerw *file);
  32. static rt_bool_t rtgui_image_xpm_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load);
  33. static void rtgui_image_xpm_unload(struct rtgui_image *image);
  34. static void rtgui_image_xpm_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect);
  35. struct rtgui_image_engine rtgui_image_xpm_engine =
  36. {
  37. "xpm",
  38. {RT_NULL},
  39. rtgui_image_xpm_check,
  40. rtgui_image_xpm_load,
  41. rtgui_image_xpm_unload,
  42. rtgui_image_xpm_blit,
  43. };
  44. struct rgb_item
  45. {
  46. char *name;
  47. rt_uint8_t r;
  48. rt_uint8_t g;
  49. rt_uint8_t b;
  50. };
  51. const struct rgb_item rgbRecord[234] =
  52. {
  53. {"AliceBlue", 240, 248, 255},
  54. {"AntiqueWhite", 250, 235, 215},
  55. {"Aquamarine", 50, 191, 193},
  56. {"Azure", 240, 255, 255},
  57. {"Beige", 245, 245, 220},
  58. {"Bisque", 255, 228, 196},
  59. {"Black", 0, 0, 0},
  60. {"BlanchedAlmond", 255, 235, 205},
  61. {"Blue", 0, 0, 255},
  62. {"BlueViolet", 138, 43, 226},
  63. {"Brown", 165, 42, 42},
  64. {"burlywood", 222, 184, 135},
  65. {"CadetBlue", 95, 146, 158},
  66. {"chartreuse", 127, 255, 0},
  67. {"chocolate", 210, 105, 30},
  68. {"Coral", 255, 114, 86},
  69. {"CornflowerBlue", 34, 34, 152},
  70. {"cornsilk", 255, 248, 220},
  71. {"Cyan", 0, 255, 255},
  72. {"DarkGoldenrod", 184, 134, 11},
  73. {"DarkGreen", 0, 86, 45},
  74. {"DarkKhaki", 189, 183, 107},
  75. {"DarkOliveGreen", 85, 86, 47},
  76. {"DarkOrange", 255, 140, 0},
  77. {"DarkOrchid", 139, 32, 139},
  78. {"DarkSalmon", 233, 150, 122},
  79. {"DarkSeaGreen", 143, 188, 143},
  80. {"DarkSlateBlue", 56, 75, 102},
  81. {"DarkSlateGray", 47, 79, 79},
  82. {"DarkTurquoise", 0, 166, 166},
  83. {"DarkViolet", 148, 0, 211},
  84. {"DeepPink", 255, 20, 147},
  85. {"DeepSkyBlue", 0, 191, 255},
  86. {"DimGray", 84, 84, 84},
  87. {"DodgerBlue", 30, 144, 255},
  88. {"Firebrick", 142, 35, 35},
  89. {"FloralWhite", 255, 250, 240},
  90. {"ForestGreen", 80, 159, 105},
  91. {"gainsboro", 220, 220, 220},
  92. {"GhostWhite", 248, 248, 255},
  93. {"Gold", 218, 170, 0},
  94. {"Goldenrod", 239, 223, 132},
  95. {"Gray", 126, 126, 126},
  96. {"Gray0", 0, 0, 0},
  97. {"Gray1", 3, 3, 3},
  98. {"Gray10", 26, 26, 26},
  99. {"Gray100", 255, 255, 255},
  100. {"Gray11", 28, 28, 28},
  101. {"Gray12", 31, 31, 31},
  102. {"Gray13", 33, 33, 33},
  103. {"Gray14", 36, 36, 36},
  104. {"Gray15", 38, 38, 38},
  105. {"Gray16", 41, 41, 41},
  106. {"Gray17", 43, 43, 43},
  107. {"Gray18", 46, 46, 46},
  108. {"Gray19", 48, 48, 48},
  109. {"Gray2", 5, 5, 5},
  110. {"Gray20", 51, 51, 51},
  111. {"Gray21", 54, 54, 54},
  112. {"Gray22", 56, 56, 56},
  113. {"Gray23", 59, 59, 59},
  114. {"Gray24", 61, 61, 61},
  115. {"Gray25", 64, 64, 64},
  116. {"Gray26", 66, 66, 66},
  117. {"Gray27", 69, 69, 69},
  118. {"Gray28", 71, 71, 71},
  119. {"Gray29", 74, 74, 74},
  120. {"Gray3", 8, 8, 8},
  121. {"Gray30", 77, 77, 77},
  122. {"Gray31", 79, 79, 79},
  123. {"Gray32", 82, 82, 82},
  124. {"Gray33", 84, 84, 84},
  125. {"Gray34", 87, 87, 87},
  126. {"Gray35", 89, 89, 89},
  127. {"Gray36", 92, 92, 92},
  128. {"Gray37", 94, 94, 94},
  129. {"Gray38", 97, 97, 97},
  130. {"Gray39", 99, 99, 99},
  131. {"Gray4", 10, 10, 10},
  132. {"Gray40", 102, 102, 102},
  133. {"Gray41", 105, 105, 105},
  134. {"Gray42", 107, 107, 107},
  135. {"Gray43", 110, 110, 110},
  136. {"Gray44", 112, 112, 112},
  137. {"Gray45", 115, 115, 115},
  138. {"Gray46", 117, 117, 117},
  139. {"Gray47", 120, 120, 120},
  140. {"Gray48", 122, 122, 122},
  141. {"Gray49", 125, 125, 125},
  142. {"Gray5", 13, 13, 13},
  143. {"Gray50", 127, 127, 127},
  144. {"Gray51", 130, 130, 130},
  145. {"Gray52", 133, 133, 133},
  146. {"Gray53", 135, 135, 135},
  147. {"Gray54", 138, 138, 138},
  148. {"Gray55", 140, 140, 140},
  149. {"Gray56", 143, 143, 143},
  150. {"Gray57", 145, 145, 145},
  151. {"Gray58", 148, 148, 148},
  152. {"Gray59", 150, 150, 150},
  153. {"Gray6", 15, 15, 15},
  154. {"Gray60", 153, 153, 153},
  155. {"Gray61", 156, 156, 156},
  156. {"Gray62", 158, 158, 158},
  157. {"Gray63", 161, 161, 161},
  158. {"Gray64", 163, 163, 163},
  159. {"Gray65", 166, 166, 166},
  160. {"Gray66", 168, 168, 168},
  161. {"Gray67", 171, 171, 171},
  162. {"Gray68", 173, 173, 173},
  163. {"Gray69", 176, 176, 176},
  164. {"Gray7", 18, 18, 18},
  165. {"Gray70", 179, 179, 179},
  166. {"Gray71", 181, 181, 181},
  167. {"Gray72", 184, 184, 184},
  168. {"Gray73", 186, 186, 186},
  169. {"Gray74", 189, 189, 189},
  170. {"Gray75", 191, 191, 191},
  171. {"Gray76", 194, 194, 194},
  172. {"Gray77", 196, 196, 196},
  173. {"Gray78", 199, 199, 199},
  174. {"Gray79", 201, 201, 201},
  175. {"Gray8", 20, 20, 20},
  176. {"Gray80", 204, 204, 204},
  177. {"Gray81", 207, 207, 207},
  178. {"Gray82", 209, 209, 209},
  179. {"Gray83", 212, 212, 212},
  180. {"Gray84", 214, 214, 214},
  181. {"Gray85", 217, 217, 217},
  182. {"Gray86", 219, 219, 219},
  183. {"Gray87", 222, 222, 222},
  184. {"Gray88", 224, 224, 224},
  185. {"Gray89", 227, 227, 227},
  186. {"Gray9", 23, 23, 23},
  187. {"Gray90", 229, 229, 229},
  188. {"Gray91", 232, 232, 232},
  189. {"Gray92", 235, 235, 235},
  190. {"Gray93", 237, 237, 237},
  191. {"Gray94", 240, 240, 240},
  192. {"Gray95", 242, 242, 242},
  193. {"Gray96", 245, 245, 245},
  194. {"Gray97", 247, 247, 247},
  195. {"Gray98", 250, 250, 250},
  196. {"Gray99", 252, 252, 252},
  197. {"Green", 0, 255, 0},
  198. {"GreenYellow", 173, 255, 47},
  199. {"honeydew", 240, 255, 240},
  200. {"HotPink", 255, 105, 180},
  201. {"IndianRed", 107, 57, 57},
  202. {"ivory", 255, 255, 240},
  203. {"Khaki", 179, 179, 126},
  204. {"lavender", 230, 230, 250},
  205. {"LavenderBlush", 255, 240, 245},
  206. {"LawnGreen", 124, 252, 0},
  207. {"LemonChiffon", 255, 250, 205},
  208. {"LightBlue", 176, 226, 255},
  209. {"LightCoral", 240, 128, 128},
  210. {"LightCyan", 224, 255, 255},
  211. {"LightGoldenrod", 238, 221, 130},
  212. {"LightGoldenrodYellow", 250, 250, 210},
  213. {"LightGray", 168, 168, 168},
  214. {"LightPink", 255, 182, 193},
  215. {"LightSalmon", 255, 160, 122},
  216. {"LightSeaGreen", 32, 178, 170},
  217. {"LightSkyBlue", 135, 206, 250},
  218. {"LightSlateBlue", 132, 112, 255},
  219. {"LightSlateGray", 119, 136, 153},
  220. {"LightSteelBlue", 124, 152, 211},
  221. {"LightYellow", 255, 255, 224},
  222. {"LimeGreen", 0, 175, 20},
  223. {"linen", 250, 240, 230},
  224. {"Magenta", 255, 0, 255},
  225. {"Maroon", 143, 0, 82},
  226. {"MediumAquamarine", 0, 147, 143},
  227. {"MediumBlue", 50, 50, 204},
  228. {"MediumForestGreen", 50, 129, 75},
  229. {"MediumGoldenrod", 209, 193, 102},
  230. {"MediumOrchid", 189, 82, 189},
  231. {"MediumPurple", 147, 112, 219},
  232. {"MediumSeaGreen", 52, 119, 102},
  233. {"MediumSlateBlue", 106, 106, 141},
  234. {"MediumSpringGreen", 35, 142, 35},
  235. {"MediumTurquoise", 0, 210, 210},
  236. {"MediumVioletRed", 213, 32, 121},
  237. {"MidnightBlue", 47, 47, 100},
  238. {"MintCream", 245, 255, 250},
  239. {"MistyRose", 255, 228, 225},
  240. {"moccasin", 255, 228, 181},
  241. {"NavajoWhite", 255, 222, 173},
  242. {"Navy", 35, 35, 117},
  243. {"NavyBlue", 35, 35, 117},
  244. {"OldLace", 253, 245, 230},
  245. {"OliveDrab", 107, 142, 35},
  246. {"Orange", 255, 135, 0},
  247. {"OrangeRed", 255, 69, 0},
  248. {"Orchid", 239, 132, 239},
  249. {"PaleGoldenrod", 238, 232, 170},
  250. {"PaleGreen", 115, 222, 120},
  251. {"PaleTurquoise", 175, 238, 238},
  252. {"PaleVioletRed", 219, 112, 147},
  253. {"PapayaWhip", 255, 239, 213},
  254. {"PeachPuff", 255, 218, 185},
  255. {"peru", 205, 133, 63},
  256. {"Pink", 255, 181, 197},
  257. {"Plum", 197, 72, 155},
  258. {"PowderBlue", 176, 224, 230},
  259. {"purple", 160, 32, 240},
  260. {"Red", 255, 0, 0},
  261. {"RosyBrown", 188, 143, 143},
  262. {"RoyalBlue", 65, 105, 225},
  263. {"SaddleBrown", 139, 69, 19},
  264. {"Salmon", 233, 150, 122},
  265. {"SandyBrown", 244, 164, 96},
  266. {"SeaGreen", 82, 149, 132},
  267. {"seashell", 255, 245, 238},
  268. {"Sienna", 150, 82, 45},
  269. {"SkyBlue", 114, 159, 255},
  270. {"SlateBlue", 126, 136, 171},
  271. {"SlateGray", 112, 128, 144},
  272. {"snow", 255, 250, 250},
  273. {"SpringGreen", 65, 172, 65},
  274. {"SteelBlue", 84, 112, 170},
  275. {"Tan", 222, 184, 135},
  276. {"Thistle", 216, 191, 216},
  277. {"tomato", 255, 99, 71},
  278. {"Transparent", 0, 0, 1},
  279. {"Turquoise", 25, 204, 223},
  280. {"Violet", 156, 62, 206},
  281. {"VioletRed", 243, 62, 150},
  282. {"Wheat", 245, 222, 179},
  283. {"White", 255, 255, 255},
  284. {"WhiteSmoke", 245, 245, 245},
  285. {"Yellow", 255, 255, 0},
  286. {"YellowGreen", 50, 216, 56}
  287. };
  288. /* Hash table to look up colors from pixel strings */
  289. #define STARTING_HASH_SIZE 256
  290. struct hash_entry
  291. {
  292. char key[10];
  293. rtgui_color_t color;
  294. struct hash_entry *next;
  295. };
  296. struct color_hash
  297. {
  298. struct hash_entry **table;
  299. struct hash_entry *entries; /* array of all entries */
  300. struct hash_entry *next_free;
  301. int size;
  302. int maxnum;
  303. };
  304. static int hash_key(const char *key, int cpp, int size)
  305. {
  306. int hash;
  307. hash = 0;
  308. while (cpp-- > 0)
  309. {
  310. hash = hash * 33 + *key++;
  311. }
  312. return hash & (size - 1);
  313. }
  314. static struct color_hash *create_colorhash(int maxnum)
  315. {
  316. int bytes, s;
  317. struct color_hash *hash;
  318. /* we know how many entries we need, so we can allocate
  319. everything here */
  320. hash = rtgui_malloc(sizeof *hash);
  321. if (!hash) return RT_NULL;
  322. /* use power-of-2 sized hash table for decoding speed */
  323. for (s = STARTING_HASH_SIZE; s < maxnum; s <<= 1) ;
  324. hash->size = s;
  325. hash->maxnum = maxnum;
  326. bytes = hash->size *sizeof(struct hash_entry **);
  327. hash->entries = RT_NULL; /* in case rt_malloc fails */
  328. hash->table = rtgui_malloc(bytes);
  329. if (!hash->table) return RT_NULL;
  330. rt_memset(hash->table, 0, bytes);
  331. hash->entries = rtgui_malloc(maxnum *sizeof(struct hash_entry));
  332. if (!hash->entries) return RT_NULL;
  333. hash->next_free = hash->entries;
  334. return hash;
  335. }
  336. static int add_colorhash(struct color_hash *hash,
  337. char *key, int cpp, rtgui_color_t *color)
  338. {
  339. int index = hash_key(key, cpp, hash->size);
  340. struct hash_entry *e = hash->next_free++;
  341. e->color = *color;
  342. rt_memset(e->key, 0, sizeof(e->key));
  343. rt_strncpy(e->key, key, cpp);
  344. e->next = hash->table[index];
  345. hash->table[index] = e;
  346. return 1;
  347. }
  348. static void get_colorhash(struct color_hash *hash, const char *key, int cpp, rtgui_color_t *c)
  349. {
  350. struct hash_entry *entry = hash->table[hash_key(key, cpp, hash->size)];
  351. while (entry)
  352. {
  353. if (rt_memcmp(key, entry->key, cpp) == 0)
  354. {
  355. *c = entry->color;
  356. return;
  357. }
  358. entry = entry->next;
  359. }
  360. return ; /* garbage in - garbage out */
  361. }
  362. static void free_colorhash(struct color_hash *hash)
  363. {
  364. if (hash && hash->table)
  365. {
  366. rtgui_free(hash->table);
  367. rtgui_free(hash->entries);
  368. rtgui_free(hash);
  369. }
  370. }
  371. #if defined(_MSC_VER) || defined(__CC_ARM)
  372. int strcasecmp(const char *s1, const char *s2)
  373. {
  374. register unsigned int x2;
  375. register unsigned int x1;
  376. while (1)
  377. {
  378. x2 = *s2 - 'A';
  379. if (x2 < 26u) x2 += 32;
  380. x1 = *s1 - 'A';
  381. if (x1 < 26u) x1 += 32;
  382. s1++;
  383. s2++;
  384. if (x2 != x1)
  385. break;
  386. if (x1 == (unsigned int) - 'A')
  387. break;
  388. }
  389. return x1 - x2;
  390. }
  391. #endif
  392. static int hex2int(const char *str)
  393. {
  394. int i = 0;
  395. int r = 0;
  396. for (i = 0; i < 2; i++)
  397. {
  398. if (str[i] >= '0' && str[i] <= '9') r += str[i] - '0';
  399. else if (str[i] >= 'a' && str[i] <= 'f') r += str[i] - 'a' + 10;
  400. else if (str[i] >= 'A' && str[i] <= 'F') r += str[i] - 'A' + 10;
  401. if (!i) r *= 16;
  402. }
  403. return r;
  404. }
  405. void rtgui_image_xpm_init()
  406. {
  407. /* register xpm engine */
  408. rtgui_image_register_engine(&rtgui_image_xpm_engine);
  409. }
  410. static rt_bool_t rtgui_image_xpm_check(struct rtgui_filerw *file)
  411. {
  412. #if 0
  413. rt_uint8_t buffer[XPM_MAGIC_LEN];
  414. rt_size_t start;
  415. rt_bool_t result;
  416. result = RT_FALSE;
  417. start = rtgui_filerw_tell(file);
  418. /* seek to the begining of file */
  419. if (start != 0) rtgui_filerw_seek(file, 0, SEEK_SET);
  420. rtgui_filerw_read(file, &buffer[0], XPM_MAGIC_LEN, 1);
  421. if (rt_memcmp(buffer, "/* XPM */", (rt_ubase_t)XPM_MAGIC_LEN) == 0)
  422. result = RT_TRUE;
  423. rtgui_filerw_seek(file, start, SEEK_SET);
  424. return result;
  425. #else
  426. /* we can not check image type for memory file */
  427. return RT_TRUE;
  428. #endif
  429. }
  430. static int _str2int(const char *str, int strlen, int *p)
  431. {
  432. int i;
  433. *p = 0;
  434. /* Skip the leading chars. */
  435. for (i = 0; i < strlen; i++)
  436. {
  437. if ('0' <= str[i] && str[i] <= '9')
  438. break;
  439. }
  440. for (; i < strlen; i++)
  441. {
  442. if (str[i] < '0' || '9' < str[i])
  443. break;
  444. *p = (*p) * 10 + str[i] - '0';
  445. }
  446. return i;
  447. }
  448. static rt_bool_t rtgui_image_xpm_load(struct rtgui_image *image, struct rtgui_filerw *file, rt_bool_t load)
  449. {
  450. const char **xpm;
  451. const char *buf;
  452. const char *buf_tmp;
  453. int w, h;
  454. int colors = 0;
  455. int colors_pp = 0;
  456. int i, j;
  457. /* color hash table */
  458. struct color_hash *colors_table = RT_NULL;
  459. if (image == RT_NULL) return RT_FALSE;
  460. xpm = (const char **)rtgui_filerw_mem_getdata(file);
  461. if (xpm == RT_NULL) return RT_FALSE;
  462. /* set image engine */
  463. image->engine = &rtgui_image_xpm_engine;
  464. /* parse xpm image */
  465. i = rt_strlen(xpm[0]);
  466. /* Add one for the space. */
  467. j = _str2int(xpm[0], i, &w) + 1;
  468. j += _str2int(xpm[0] + j, i - j, &h) + 1;
  469. j += _str2int(xpm[0] + j, i - j, &colors) + 1;
  470. j += _str2int(xpm[0] + j, i - j, &colors_pp) + 1;
  471. image->w = w;
  472. image->h = h;
  473. /* build color table */
  474. colors_table = create_colorhash(colors);
  475. if (!colors_table)
  476. {
  477. return RT_FALSE;
  478. }
  479. for (i = 0; i < colors; i++)
  480. {
  481. char color_name[10];
  482. rtgui_color_t c = 0;
  483. buf = xpm[i + 1];
  484. for (j = 0; j < colors_pp; j++)
  485. {
  486. color_name[j] = buf[j];
  487. }
  488. color_name[j] = '\0';
  489. /* build rtgui_color */
  490. if ((buf_tmp = strstr(buf, "c #")) != RT_NULL)
  491. {
  492. c = RTGUI_ARGB(0, hex2int(buf_tmp + 3),
  493. hex2int(buf_tmp + 5),
  494. hex2int(buf_tmp + 7));
  495. }
  496. else if ((buf_tmp = strstr(buf, "c ")) != RT_NULL)
  497. {
  498. int k;
  499. if (strcasecmp(buf_tmp + 2, "None") == 0)
  500. {
  501. goto color_none;
  502. }
  503. for (k = 0; k < 234; k++)
  504. {
  505. if (strcasecmp(buf_tmp + 2, rgbRecord[k].name) == 0)
  506. {
  507. c = RTGUI_ARGB(0, rgbRecord[k].r,
  508. rgbRecord[k].g,
  509. rgbRecord[k].b);
  510. break;
  511. }
  512. }
  513. }
  514. else
  515. {
  516. color_none:
  517. c = RTGUI_RGB(0, 0, 0);
  518. }
  519. /* add to color hash table */
  520. add_colorhash(colors_table, color_name, colors_pp, &c);
  521. }
  522. /* build rgb pixel data */
  523. image->data = (rt_uint8_t *) rtgui_malloc(image->w * image->h * sizeof(rtgui_color_t));
  524. memset(image->data, 0, image->w * image->h * sizeof(rtgui_color_t));
  525. {
  526. rtgui_color_t *ptr = (rtgui_color_t *) image->data;
  527. for (h = 0; h < image->h; h++)
  528. {
  529. buf = xpm[colors + 1 + h];
  530. for (w = 0; w < image->w; w++, buf += colors_pp)
  531. {
  532. get_colorhash(colors_table, buf, colors_pp, ptr);
  533. ptr ++;
  534. }
  535. }
  536. }
  537. free_colorhash(colors_table);
  538. rtgui_filerw_close(file);
  539. return RT_TRUE;
  540. }
  541. static void rtgui_image_xpm_unload(struct rtgui_image *image)
  542. {
  543. if (image != RT_NULL)
  544. {
  545. /* release data */
  546. rtgui_free(image->data);
  547. image->data = RT_NULL;
  548. }
  549. }
  550. static void rtgui_image_xpm_blit(struct rtgui_image *image, struct rtgui_dc *dc, struct rtgui_rect *rect)
  551. {
  552. rt_uint16_t x, y;
  553. rtgui_color_t *ptr;
  554. RT_ASSERT(image != RT_NULL && dc != RT_NULL && rect != RT_NULL);
  555. RT_ASSERT(image->data != RT_NULL);
  556. ptr = (rtgui_color_t *) image->data;
  557. /* draw each point within dc */
  558. for (y = 0; y < image->h; y ++)
  559. {
  560. for (x = 0; x < image->w; x++)
  561. {
  562. /* not alpha */
  563. if ((*ptr >> 24) != 255)
  564. {
  565. rtgui_dc_draw_color_point(dc, x + rect->x1, y + rect->y1, *ptr);
  566. }
  567. /* move to next color buffer */
  568. ptr ++;
  569. }
  570. }
  571. }
  572. #endif