ml_imagelist.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384
  1. #include "./ml_imagelist.h"
  2. #include "../nu/trace.h"
  3. typedef struct _MLILSTATE
  4. {
  5. INT ilIndex;
  6. COLORREF rgbBk;
  7. COLORREF rgbFg;
  8. UINT created;
  9. UINT counter;
  10. } MLILSTATE;
  11. typedef struct _MLILREC
  12. {
  13. MLIMAGESOURCE_I imgSource;
  14. GUID filterUID;
  15. UINT filterFlags;
  16. INT_PTR tag;
  17. MLILSTATE *states;
  18. INT usedCount;
  19. INT lastIndex;
  20. UINT counter;
  21. } MLILREC;
  22. typedef struct _MLIL
  23. {
  24. HIMAGELIST ilImages;
  25. INT maxCache;
  26. INT imageWidth;
  27. INT imageHeight;
  28. UINT flags;
  29. MLILREC *records;
  30. INT recCount;
  31. INT recAllocated;
  32. INT recGrow;
  33. HMLIMGFLTRMNGR hmlifMngr;
  34. } MLIL;
  35. static BOOL MLImageListI_PatchHILIndices(HMLIMGLST hmlil, INT hilIndex) // scan for all records - states and subtract 1 from all indices that higher than hilIndex.
  36. {
  37. INT index, stateIdx;
  38. MLIL *pmlil;
  39. if (!hmlil || hilIndex < 0 ) return FALSE;
  40. pmlil = (MLIL*)hmlil;
  41. for (index = 0; index < pmlil->recCount; index++)
  42. {
  43. if (pmlil->records[index].states)
  44. {
  45. for (stateIdx = 0; stateIdx < pmlil->records[index].usedCount; stateIdx++)
  46. {
  47. if (pmlil->records[index].states[stateIdx].ilIndex > hilIndex) pmlil->records[index].states[stateIdx].ilIndex--;
  48. }
  49. }
  50. }
  51. return TRUE;
  52. }
  53. HMLIMGLST MLImageListI_Create(INT cx, INT cy, UINT flags, INT cInitial, INT cGrow, INT cCacheSize, HMLIMGFLTRMNGR hmlifManager)
  54. {
  55. if (!cx || !cy || !cCacheSize) return NULL;
  56. MLIL *pmlil = (MLIL*)calloc(1, sizeof(MLIL));
  57. if (!pmlil) return NULL;
  58. BOOL fSuccess = TRUE;
  59. if (!(0x38 & pmlil->flags)) pmlil->flags |= MLILC_COLOR24_I;
  60. pmlil->imageWidth = cx;
  61. pmlil->imageHeight = cy;
  62. pmlil->flags = flags;
  63. pmlil->recAllocated = (cGrow < 0 ) ? 0 : ((cInitial > MAX_ALLOWED_LIST_SIZE) ? MAX_ALLOWED_LIST_SIZE : cInitial);
  64. pmlil->recGrow = (cGrow < 1 ) ? 1 : ((cGrow > MAX_ALLOWED_LIST_SIZE) ? MAX_ALLOWED_LIST_SIZE : cGrow);
  65. pmlil->maxCache = (cCacheSize > MAX_ALLOWED_CACHE_SIZE) ? MAX_ALLOWED_CACHE_SIZE : cCacheSize;
  66. pmlil->hmlifMngr = hmlifManager;
  67. if (pmlil->recAllocated)
  68. {
  69. pmlil->records = (MLILREC*)calloc(pmlil->recAllocated, sizeof(MLILREC));
  70. if (!pmlil->records) fSuccess = FALSE;
  71. else
  72. {
  73. pmlil->ilImages = ImageList_Create(pmlil->imageWidth, pmlil->imageHeight, pmlil->flags, pmlil->recAllocated * pmlil->maxCache, pmlil->recGrow * pmlil->maxCache);
  74. if (!pmlil->ilImages) fSuccess = FALSE;
  75. }
  76. }
  77. if (!fSuccess && pmlil)
  78. {
  79. if (pmlil->records) free(pmlil->records);
  80. if (pmlil->ilImages) ImageList_Destroy(pmlil->ilImages);
  81. free(pmlil);
  82. pmlil = NULL;
  83. }
  84. return (HMLIMGLST)pmlil;
  85. }
  86. BOOL MLImageListI_Destroy(HMLIMGLST hmlil)
  87. {
  88. if (!hmlil) return FALSE;
  89. if (((MLIL*)hmlil)->records)
  90. {
  91. for (INT index = 0; index < ((MLIL*)hmlil)->recCount; index++)
  92. {
  93. if (((MLIL*)hmlil)->records[index].states) free(((MLIL*)hmlil)->records[index].states);
  94. MLImageLoaderI_FreeData(&((MLIL*)hmlil)->records[index].imgSource);
  95. }
  96. free(((MLIL*)hmlil)->records);
  97. }
  98. if (((MLIL*)hmlil)->ilImages) ImageList_Destroy(((MLIL*)hmlil)->ilImages);
  99. free(hmlil);
  100. return TRUE;
  101. }
  102. INT MLImageListI_Add(HMLIMGLST hmlil, MLIMAGESOURCE_I *pImageSource, REFGUID filterUID, INT_PTR nTag)
  103. {
  104. MLIL *pmlil;
  105. MLIMAGEFILTERINFO_I fi;
  106. if (!hmlil || !pImageSource) return -1;
  107. pmlil = (MLIL*)hmlil;
  108. if (pmlil->recCount == pmlil->recAllocated)
  109. {
  110. LPVOID data;
  111. data = realloc(pmlil->records, sizeof(MLILREC)* (pmlil->recAllocated + pmlil->recGrow));
  112. if (!data) return -1;
  113. pmlil->records = (MLILREC*)data;
  114. pmlil->recAllocated += pmlil->recGrow;
  115. if (!pmlil->ilImages)
  116. {
  117. pmlil->ilImages = ImageList_Create(pmlil->imageWidth, pmlil->imageHeight, pmlil->flags,
  118. pmlil->recAllocated * pmlil->maxCache, pmlil->recGrow * pmlil->maxCache);
  119. }
  120. }
  121. if (!pmlil->ilImages) return -1;
  122. ZeroMemory(&pmlil->records[pmlil->recCount], sizeof(MLILREC));
  123. if (!MLImageLoaderI_CopyData(&pmlil->records[pmlil->recCount].imgSource, pImageSource)) return -1;
  124. pmlil->records[pmlil->recCount].filterUID = filterUID;
  125. pmlil->records[pmlil->recCount].tag = nTag;
  126. pmlil->records[pmlil->recCount].lastIndex = -1;
  127. fi.uid = filterUID;
  128. fi.mask = MLIFF_FLAGS_I;
  129. pmlil->records[pmlil->recCount].filterFlags = (MLImageFilterI_GetInfo(pmlil->hmlifMngr, &fi)) ? fi.fFlags : 0;
  130. return pmlil->recCount++;
  131. }
  132. BOOL MLImageListI_Replace(HMLIMGLST hmlil, INT index, MLIMAGESOURCE_I *pImageSource, REFGUID filterUID, INT_PTR nTag)
  133. {
  134. MLIL *pmlil;
  135. MLIMAGEFILTERINFO_I fi;
  136. if (!hmlil || !pImageSource) return FALSE;
  137. pmlil = (MLIL*)hmlil;
  138. if (index < 0 || index >= pmlil->recCount) return FALSE;
  139. MLImageLoaderI_FreeData(&pmlil->records[index].imgSource);
  140. if (!MLImageLoaderI_CopyData(&pmlil->records[index].imgSource, pImageSource)) return -1;
  141. if (pmlil->records[index].states)
  142. {
  143. free(pmlil->records[index].states);
  144. pmlil->records[index].states = NULL;
  145. }
  146. pmlil->records[index].filterUID = filterUID;
  147. pmlil->records[index].tag = nTag;
  148. pmlil->records[index].lastIndex = -1;
  149. pmlil->records[index].usedCount = 0;
  150. pmlil->records[index].counter = 0;
  151. fi.uid = filterUID;
  152. fi.mask = MLIFF_FLAGS_I;
  153. pmlil->records[index].filterFlags = (MLImageFilterI_GetInfo(pmlil->hmlifMngr, &fi)) ? fi.fFlags : 0;
  154. return TRUE;
  155. }
  156. BOOL MLImageListI_Remove(HMLIMGLST hmlil, INT index)
  157. {
  158. MLIL *pmlil;
  159. if (!hmlil) return FALSE;
  160. pmlil = (MLIL*)hmlil;
  161. if (index < 0 || index >= pmlil->recCount) return FALSE;
  162. MLImageLoaderI_FreeData(&pmlil->records[index].imgSource);
  163. if (pmlil->records[index].states)
  164. {
  165. INT stateIdx;
  166. for (stateIdx = 0; stateIdx < pmlil->records[index].usedCount; stateIdx++)
  167. {
  168. INT hilIdx = pmlil->records[index].states[stateIdx].ilIndex;
  169. if (-1 != hilIdx && ImageList_Remove(pmlil->ilImages, hilIdx)) MLImageListI_PatchHILIndices(hmlil, hilIdx);
  170. }
  171. free(pmlil->records[index].states);
  172. }
  173. if (index != (pmlil->recCount - 1)) MoveMemory(&pmlil->records[index], &pmlil->records[index + 1], sizeof(MLILREC)*(pmlil->recCount - index));
  174. pmlil->recCount--;
  175. return TRUE;
  176. }
  177. HIMAGELIST MLImageListI_GetRealList(HMLIMGLST hmlil)
  178. {
  179. return (hmlil) ? ((MLIL*)hmlil)->ilImages : NULL;
  180. }
  181. INT MLImageListI_GetRealIndex(HMLIMGLST hmlil, INT index, COLORREF rgbBk, COLORREF rgbFg)
  182. {
  183. INT realIndex;
  184. MLIL *pmlil;
  185. MLILREC *prec;
  186. HBITMAP hbmp;
  187. pmlil = (MLIL*)hmlil;
  188. if (!pmlil || index < 0 || index >= pmlil->recCount)
  189. return -1;
  190. prec = &pmlil->records[index];
  191. if (MLIFF_IGNORE_FGCOLOR_I & prec->filterFlags)
  192. rgbFg = 0xFFFF00FF;
  193. if (MLIFF_IGNORE_BKCOLOR_I & prec->filterFlags)
  194. rgbBk = 0xFFFF00FF;
  195. if (pmlil->ilImages && prec->states && prec->usedCount > 0)
  196. {
  197. if (prec->lastIndex >= 0 && prec->lastIndex < prec->usedCount &&
  198. prec->states[prec->lastIndex].rgbBk == rgbBk && prec->states[prec->lastIndex].rgbFg == rgbFg) realIndex = prec->lastIndex;
  199. else
  200. {
  201. for (realIndex = 0; realIndex < prec->usedCount; realIndex++)
  202. {
  203. if (prec->states[realIndex].rgbBk == rgbBk && prec->states[realIndex].rgbFg == rgbFg)
  204. {
  205. prec->lastIndex = realIndex;
  206. break;
  207. }
  208. }
  209. }
  210. if (prec->lastIndex == realIndex && -1 != prec->states[realIndex].ilIndex)
  211. {
  212. prec->counter++;
  213. prec->states[realIndex].counter++;
  214. return prec->states[realIndex].ilIndex;
  215. }
  216. }
  217. hbmp = MLImageLoaderI_LoadDib(&prec->imgSource);
  218. if (!hbmp)
  219. return -1;
  220. if (!MLImageFilterI_Apply(pmlil->hmlifMngr, &prec->filterUID, hbmp, rgbBk, rgbFg, prec->tag))
  221. {
  222. rgbFg = 0xFFFF00FF;
  223. rgbBk = 0xFFFF00FF;
  224. }
  225. if (!prec->states)
  226. {
  227. prec->states = (MLILSTATE*)calloc(pmlil->maxCache, sizeof(MLILSTATE));
  228. if (!prec->states)
  229. {
  230. DeleteObject(hbmp);
  231. return -1;
  232. }
  233. prec->counter = 0;
  234. prec->lastIndex = -1;
  235. prec->usedCount = 0;
  236. }
  237. if (prec->usedCount < pmlil->maxCache)
  238. {
  239. realIndex = prec->usedCount++;
  240. prec->states[realIndex].ilIndex = -1;
  241. }
  242. else
  243. { /// lets find less used record
  244. INT minVal, minIndex;
  245. minIndex = 0;
  246. minVal = (prec->counter != prec->states[minIndex].created) ?
  247. (prec->counter - prec->states[minIndex].created) :
  248. 1;
  249. minVal = MulDiv(100000, prec->states[minIndex].counter, minVal);
  250. for (realIndex = 0; realIndex < prec->usedCount; realIndex++)
  251. {
  252. INT testVal = (prec->counter != prec->states[realIndex].created) ?
  253. (prec->counter - prec->states[realIndex].created) :
  254. 1;
  255. testVal = MulDiv(100000, prec->states[realIndex].counter, testVal);
  256. if (testVal < minVal)
  257. {
  258. minVal = testVal;
  259. minIndex = realIndex;
  260. }
  261. }
  262. realIndex = minIndex;
  263. }
  264. prec->states[realIndex].rgbBk = rgbBk;
  265. prec->states[realIndex].rgbFg = rgbFg;
  266. prec->states[realIndex].counter = 1;
  267. prec->states[realIndex].created = prec->counter;
  268. if(NULL != pmlil->ilImages)
  269. {
  270. if (-1 == prec->states[realIndex].ilIndex)
  271. prec->states[realIndex].ilIndex = ImageList_Add(pmlil->ilImages, hbmp, NULL);
  272. else
  273. ImageList_Replace(pmlil->ilImages, prec->states[realIndex].ilIndex, hbmp, NULL);
  274. }
  275. DeleteObject(hbmp);
  276. if (-1 != prec->states[realIndex].ilIndex)
  277. {
  278. prec->counter++;
  279. prec->lastIndex = realIndex;
  280. }
  281. return prec->states[realIndex].ilIndex;
  282. }
  283. BOOL MLImageListI_GetImageSize(HMLIMGLST hmlil, INT *cx, INT *cy)
  284. {
  285. if (!hmlil)
  286. {
  287. if (cx) *cx = 0;
  288. if (cy) *cy = 0;
  289. return FALSE;
  290. }
  291. if (cx) *cx = ((MLIL*)hmlil)->imageWidth;
  292. if (cy) *cy = ((MLIL*)hmlil)->imageHeight;
  293. return TRUE;
  294. }
  295. INT MLImageListI_GetImageCount(HMLIMGLST hmlil)
  296. {
  297. return (hmlil) ? ((MLIL*)hmlil)->recCount : 0;
  298. }
  299. INT MLImageListI_GetIndexFromTag(HMLIMGLST hmlil, INT_PTR nTag)
  300. {
  301. INT index;
  302. if (!hmlil || !((MLIL*)hmlil)->records) return -1;
  303. for (index = 0; index <((MLIL*)hmlil)->recCount; index++)
  304. {
  305. if (((MLIL*)hmlil)->records[index].tag == nTag) return index;
  306. }
  307. return -1;
  308. }
  309. BOOL MLImageListI_GetTagFromIndex(HMLIMGLST hmlil, INT index, INT_PTR *nTag)
  310. {
  311. if (!hmlil || !((MLIL*)hmlil)->records || index < 0 || index >= ((MLIL*)hmlil)->recCount) return FALSE;
  312. if (nTag) *nTag = ((MLIL*)hmlil)->records[index].tag;
  313. return TRUE;
  314. }
  315. BOOL MLImageListI_CheckItemExist(HMLIMGLST hmlil, INT index)
  316. {
  317. MLIL *pmlil = (MLIL*)hmlil;
  318. if (NULL == pmlil || index < 0 || index >= pmlil->recCount) return FALSE;
  319. return MLImageLoaderI_CheckExist(&pmlil->records[index].imgSource);
  320. }