palette.inc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348
  1. {
  2. Free Pascal port of the Hermes C library.
  3. Copyright (C) 2001-2003 Nikolay Nikolov ([email protected])
  4. Original C version by Christian Nentwich ([email protected])
  5. This library is free software; you can redistribute it and/or
  6. modify it under the terms of the GNU Lesser General Public
  7. License as published by the Free Software Foundation; either
  8. version 2.1 of the License, or (at your option) any later version.
  9. This library is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. Lesser General Public License for more details.
  13. You should have received a copy of the GNU Lesser General Public
  14. License along with this library; if not, write to the Free Software
  15. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  16. }
  17. Type
  18. PHermesLookupTable = ^THermesLookupTable;
  19. THermesLookupTable = Record
  20. data : ^int32; { Actual lookup table }
  21. valid : Boolean; { Is this table up to date? }
  22. format : THermesFormat; { Format of lookup table }
  23. End;
  24. PHermesPalette = ^THermesPalette;
  25. THermesPalette = Record
  26. data : ^int32; { Palette data }
  27. tables : PHermesList; { Linked list of HermesLookupTables }
  28. End;
  29. Const
  30. PaletteList : PHermesList = Nil;
  31. PALETTErefcount : Integer = 0;
  32. currenthandle : THermesHandle = 0;
  33. {Function Hermes_PaletteGetTable(palette : THermesHandle; format : PHermesFormat) : Pointer;
  34. Procedure Hermes_PaletteMakeLookup(lookup, palette : Pint32;
  35. format : PHermesFormat);
  36. Function Hermes_PaletteInstance : THermesHandle;
  37. Procedure Hermes_PaletteReturn(handle : THermesHandle);
  38. Procedure Hermes_PaletteSet(handle : THermesHandle; palette : Pointer);
  39. Function Hermes_PaletteGet(handle : THermesHandle) : Pointer;
  40. Procedure Hermes_PaletteInvalidateCache(handle : THermesHandle);}
  41. Function Hermes_PaletteInstance : THermesHandle;
  42. Var
  43. newinstance : PHermesPalette;
  44. newelement : PHermesListElement;
  45. Begin
  46. If PaletteList = Nil Then
  47. Begin
  48. PaletteList := Hermes_ListNew;
  49. { Could not create a new list }
  50. If PaletteList = Nil Then
  51. Begin
  52. Hermes_PaletteInstance := 0;
  53. Exit;
  54. End;
  55. End;
  56. { Create a new palette structure }
  57. newinstance := malloc(SizeOf(THermesPalette));
  58. If newinstance = Nil Then
  59. Begin
  60. Hermes_PaletteInstance := 0;
  61. Exit;
  62. End;
  63. { Create palette data }
  64. newinstance^.data := malloc(256*SizeOf(int32));
  65. If newinstance^.data = Nil Then
  66. Begin
  67. free(newinstance);
  68. Hermes_PaletteInstance := 0;
  69. Exit;
  70. End;
  71. { Create lookup table list }
  72. newinstance^.tables := Hermes_ListNew;
  73. If newinstance^.tables = Nil Then
  74. Begin
  75. free(newinstance^.data);
  76. free(newinstance);
  77. Hermes_PaletteInstance := 0;
  78. Exit;
  79. End;
  80. { Everything fine so far, create a new list element }
  81. newelement := Hermes_ListElementNew(currenthandle+1);
  82. If newelement = Nil Then
  83. Begin
  84. Hermes_ListDestroy(newinstance^.tables);
  85. free(newinstance^.data);
  86. free(newinstance);
  87. Hermes_PaletteInstance := 0;
  88. Exit;
  89. End;
  90. { No errors, put current palette structure into the list element and add
  91. that to the list }
  92. newelement^.data := newinstance;
  93. Hermes_ListAdd(PaletteList, newelement);
  94. Inc(PALETTErefcount);
  95. Inc(currenthandle);
  96. Hermes_PaletteInstance := currenthandle;
  97. End;
  98. Procedure Hermes_PaletteReturn(handle : THermesHandle);
  99. Var
  100. element : PHermesListElement;
  101. pal : PHermesPalette;
  102. table : PHermesLookupTable;
  103. Begin
  104. element := Hermes_ListLookup(PaletteList, handle);
  105. If element = Nil Then
  106. Exit;
  107. pal := element^.data;
  108. { Free palette data and lookup tables }
  109. free(pal^.data);
  110. element := pal^.tables^.first;
  111. While element <> Nil Do
  112. Begin
  113. table := element^.data;
  114. If (table <> Nil) And (table^.data <> Nil) Then
  115. Begin
  116. free(table^.data);
  117. table^.data := Nil;
  118. End;
  119. element := element^.next;
  120. End;
  121. Hermes_ListDestroy(pal^.tables);
  122. { Delete list element that holds this palette }
  123. Hermes_ListDeleteElement(PaletteList, handle);
  124. { Decrease reference count. If down to zero, delete palette list }
  125. Dec(PALETTErefcount);
  126. If PALETTErefcount = 0 Then
  127. Begin
  128. Hermes_ListDestroy(PaletteList);
  129. PaletteList := Nil;
  130. End;
  131. End;
  132. Procedure Hermes_PaletteSet(handle : THermesHandle; palette : Pointer);
  133. Var
  134. element : PHermesListElement;
  135. pal : PHermesPalette;
  136. Begin
  137. { DebugMSG('Hermes_PaletteSet('+C2Str(handle)+','+C2Str(DWord(palette))+')');}
  138. element := Hermes_ListLookup(PaletteList, handle);
  139. If element = Nil Then
  140. Exit;
  141. pal := element^.data;
  142. element := pal^.tables^.first;
  143. { Invalidate all lookup tables }
  144. While element <> Nil Do
  145. Begin
  146. (PHermesLookupTable(element^.data))^.valid := False;
  147. element := element^.next;
  148. End;
  149. { FillChar(palette^, 256*4, $7f);}
  150. Move(palette^, pal^.data^, 256*4);
  151. End;
  152. Function Hermes_PaletteGet(handle : THermesHandle) : Pointer;
  153. Var
  154. element : PHermesListElement;
  155. pal : PHermesPalette;
  156. Begin
  157. element := Hermes_ListLookup(PaletteList, handle);
  158. If element = Nil Then
  159. Begin
  160. Hermes_PaletteGet := Nil;
  161. Exit;
  162. End;
  163. pal := element^.data;
  164. Hermes_PaletteGet := pal^.data;
  165. End;
  166. Procedure Hermes_PaletteMakeLookup(lookup, palette : Pint32;
  167. format : PHermesFormat);
  168. Var
  169. info : THermesGenericInfo;
  170. I : Integer;
  171. r, g, b : int32;
  172. Begin
  173. { DebugMSG('Yo! Hermes_PaletteMakeLookup');}
  174. r := 0;
  175. g := 0;
  176. b := 0;
  177. If format^.indexed Then
  178. Exit;
  179. Hermes_Calculate_Generic_Info(24,16,8,32,
  180. Hermes_Topbit(format^.r),
  181. Hermes_Topbit(format^.g),
  182. Hermes_Topbit(format^.b),
  183. Hermes_Topbit(format^.a),
  184. @info);
  185. { Optimised loop if there are no left shifts }
  186. If (info.r_left = 0) And (info.g_left = 0) And (info.b_left = 0) Then
  187. For I := 0 To 255 Do
  188. Begin
  189. r := (palette[i] Shr info.r_right) And format^.r;
  190. g := (palette[i] Shr info.g_right) And format^.g;
  191. b := (palette[i] Shr info.b_right) And format^.b;
  192. lookup[i] := r Or g Or b;
  193. End
  194. Else
  195. For I := 0 To 255 Do
  196. Begin
  197. r := ((palette[i] Shr info.r_right) Shl info.r_left) And format^.r;
  198. g := ((palette[i] Shr info.g_right) Shl info.g_left) And format^.g;
  199. b := ((palette[i] Shr info.b_right) Shl info.b_left) And format^.b;
  200. lookup[i] := r Or g Or b;
  201. End;
  202. End;
  203. Function Hermes_PaletteGetTable(palette : THermesHandle; format : PHermesFormat) : Pointer;
  204. Var
  205. element : PHermesListElement;
  206. pal : PHermesPalette;
  207. table : PHermesLookupTable;
  208. Begin
  209. element := Hermes_ListLookup(PaletteList, palette);
  210. If element = Nil Then
  211. Begin
  212. Hermes_PaletteGetTable := Nil;
  213. Exit;
  214. End;
  215. pal := element^.data;
  216. { Go to the first table in the list }
  217. element := pal^.tables^.first;
  218. { Search for correct table using format }
  219. While element <> Nil Do
  220. Begin
  221. table := element^.data;
  222. If Hermes_FormatEquals(@table^.format, format) Then
  223. Begin
  224. If table^.valid Then
  225. Begin
  226. Hermes_PaletteGetTable := table^.data;
  227. Exit;
  228. End;
  229. { Have to recreate the lookup table }
  230. Hermes_PaletteMakeLookup(table^.data, pal^.data, format);
  231. table^.valid := True;
  232. Hermes_PaletteGetTable := table^.data;
  233. Exit;
  234. End;
  235. element := element^.next;
  236. End;
  237. { Format not found, have to create a new table (need no handle) }
  238. table := malloc(SizeOf(THermesLookupTable));
  239. If table = Nil Then
  240. Begin
  241. Hermes_PaletteGetTable := Nil;
  242. Exit;
  243. End;
  244. table^.data := malloc(1024);
  245. If table^.data = Nil Then
  246. Begin
  247. Hermes_PaletteGetTable := Nil;
  248. Exit;
  249. End;
  250. { Create lookup table }
  251. Hermes_PaletteMakeLookup(table^.data, pal^.data, format);
  252. Hermes_FormatCopy(format, @table^.format);
  253. table^.valid := True;
  254. { Create a new list element }
  255. element := Hermes_ListElementNew(0);
  256. If element = Nil Then
  257. Begin
  258. Hermes_PaletteGetTable := Nil;
  259. Exit;
  260. End;
  261. element^.data := table;
  262. { Add to the front of the list }
  263. Hermes_ListAddFront(pal^.tables, element);
  264. { Return lookup data }
  265. Hermes_PaletteGetTable := table^.data;
  266. End;
  267. Procedure Hermes_PaletteInvalidateCache(handle : THermesHandle);
  268. Var
  269. element : PHermesListElement;
  270. pal : PHermesPalette;
  271. Begin
  272. element := Hermes_ListLookup(PaletteList, handle);
  273. If element = Nil Then
  274. Exit;
  275. pal := element^.data;
  276. element := pal^.tables^.first;
  277. { Invalidate all lookup tables }
  278. While element <> Nil Do
  279. Begin
  280. (PHermesLookupTable(element^.data))^.valid := False;
  281. element := element^.next;
  282. End;
  283. End;