convert.inc 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  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. {Function Hermes_ConverterInstance(flags : DWord) : THermesHandle;
  18. Procedure Hermes_ConverterReturn(handle : THermesHandle);}
  19. Var
  20. { ConverterList is a list of HermesConverter* }
  21. ConverterList : ^PHermesConverter;
  22. ConvertCurrenthandle : THermesHandle;
  23. Const
  24. lastConverter : Integer = 0; { Array size, one beyond end }
  25. CONVERTrefcount : Integer = 0;
  26. Function Hermes_ConverterInstance(flags : DWord) : THermesHandle;
  27. Var
  28. i : Integer;
  29. newinstance : PHermesConverter;
  30. newlist : ^PHermesConverter;
  31. Begin
  32. { Initialising, allocate initial size array of converters }
  33. If CONVERTrefcount = 0 Then
  34. Begin
  35. ConverterList := malloc(SizeOf(PHermesConverter) * HERMES_INITIAL);
  36. If ConverterList = Nil Then
  37. Begin
  38. Hermes_ConverterInstance := 0;
  39. Exit;
  40. End;
  41. lastConverter := HERMES_INITIAL;
  42. ConvertCurrenthandle := 1;
  43. For i := 0 To lastConverter - 1 Do
  44. ConverterList[i] := Nil;
  45. { DEBUG_PRINT("Creating dynamic array(convert.c:57), size %d\n",HERMES_INITIAL)}
  46. End;
  47. { Uh oh, arrary too small, time for growth }
  48. If ConvertCurrenthandle = lastConverter Then
  49. Begin
  50. { I'm told realloc isn't completely portable !? Let's do it by hand }
  51. newlist := malloc(SizeOf(PHermesConverter)*(lastConverter+HERMES_GROWTH));
  52. If newlist = Nil Then
  53. Begin
  54. Hermes_ConverterInstance := 0;
  55. Exit;
  56. End;
  57. { Copy converter pointers }
  58. For i := 0 To lastConverter - 1 Do
  59. newlist[i] := ConverterList[i];
  60. free(ConverterList);
  61. { Assign new list to old one }
  62. ConverterList := newlist;
  63. Inc(lastConverter, HERMES_GROWTH);
  64. { DEBUG_PRINT("Growing dynamic array, new size %d\n",lastConverter)}
  65. End;
  66. { Create a HermesConverter }
  67. newinstance := malloc(sizeof(THermesConverter));
  68. If newinstance = Nil Then
  69. Begin
  70. Hermes_ConverterInstance := 0;
  71. Exit;
  72. End;
  73. { Zero it out }
  74. newinstance^.loopnormal := Nil;
  75. newinstance^.loopstretch := Nil;
  76. newinstance^.normal := Nil;
  77. newinstance^.stretch := Nil;
  78. newinstance^.dither := Nil;
  79. newinstance^.ditherstretch := Nil;
  80. newinstance^.flags := flags;
  81. FillChar(newinstance^.source, 0, SizeOf(THermesFormat));
  82. FillChar(newinstance^.dest, 0, SizeOf(THermesFormat));
  83. ConverterList[ConvertCurrenthandle] := newinstance;
  84. Inc(CONVERTrefcount);
  85. Inc(ConvertCurrenthandle);
  86. Hermes_ConverterInstance := ConvertCurrenthandle - 1;
  87. End;
  88. Procedure Hermes_ConverterReturn(handle : THermesHandle);
  89. Begin
  90. If (handle < 0) Or (handle >= lastConverter) Then
  91. Exit;
  92. { Adjust reference count }
  93. Dec(CONVERTrefcount);
  94. If ConverterList[handle] <> Nil Then
  95. Begin
  96. free(ConverterList[handle]);
  97. ConverterList[handle] := Nil;
  98. End;
  99. { No more references, deinitialise }
  100. If CONVERTrefcount = 0 Then
  101. Begin
  102. If ConverterList <> Nil Then
  103. Begin
  104. free(ConverterList);
  105. ConverterList := Nil;
  106. End;
  107. ConvertCurrenthandle := 0;
  108. lastConverter := 0;
  109. End;
  110. End;
  111. Function Hermes_ConverterRequest(handle : THermesHandle;
  112. source, dest : PHermesFormat) : Boolean;
  113. Var
  114. searchlist : Integer;
  115. i : Integer;
  116. found : Boolean;
  117. cnv : PHermesConverter;
  118. Begin
  119. { DebugMSG('Hermes_ConverterRequest(' + C2Str(source^.bits)
  120. + ',' + C2Str(source^.r) + ',' + C2Str(source^.g) + ',' +
  121. C2Str(source^.b) + ';' + C2Str(dest^.bits)
  122. + ',' + C2Str(dest^.r) + ',' + C2Str(dest^.g) + ',' +
  123. C2Str(dest^.b) + ')');}
  124. Hermes_ConverterRequest := False;
  125. searchlist := 0;
  126. i := 0;
  127. found := False;
  128. { Check array ranges }
  129. If (handle < 0) Or (handle >= lastConverter) Then
  130. Exit;
  131. If ConverterList[handle] = Nil Then
  132. Exit;
  133. cnv := ConverterList[handle];
  134. { Cache repeated requests of the same conversion }
  135. If Hermes_FormatEquals(source, @ConverterList[handle]^.source) And
  136. Hermes_FormatEquals(dest, @ConverterList[handle]^.dest) Then
  137. Begin
  138. Hermes_ConverterRequest := True;
  139. Exit;
  140. End;
  141. { Clear the generic converter flag }
  142. cnv^.flags := cnv^.flags And (Not HERMES_CONVERT_GENERIC);
  143. { If the source and destination are equal, use copy routines }
  144. If Hermes_FormatEquals(source, dest) Then
  145. Begin
  146. { DebugMSG('format equals!');}
  147. If ((source^.bits And 7) <> 0) Or (source^.bits > 32) Or
  148. (source^.bits = 0) Then
  149. Exit;
  150. i := (source^.bits Shr 3) - 1;
  151. If equalConverters[i] = Nil Then
  152. Exit;
  153. Hermes_FormatCopy(source, @cnv^.source);
  154. Hermes_FormatCopy(dest, @cnv^.dest);
  155. cnv^.loopnormal := equalConverters[i]^.loopnormal;
  156. cnv^.loopstretch := equalConverters[i]^.loopstretch;
  157. cnv^.normal := equalConverters[i]^.normal;
  158. cnv^.stretch := equalConverters[i]^.stretch;
  159. Hermes_ConverterRequest := True;
  160. Exit;
  161. End;
  162. { Start looking for specialised converters }
  163. searchlist := $ff;
  164. Case source^.bits Of
  165. 32 : If (source^.r = $ff0000) And (source^.g = $ff00) And (source^.b = $ff) Then
  166. searchlist := 0
  167. Else
  168. If (source^.r = ($ff Shl 20)) And
  169. (source^.g = ($ff Shl 10)) And
  170. (source^.b = $ff) Then
  171. searchlist := 3;
  172. 24 : If (source^.r = $ff0000) And (source^.g = $ff00) And (source^.b = $ff) Then
  173. searchlist := 1;
  174. 16 : If (source^.r = $f800) And (source^.g = $7e0) And (source^.b = $1f) Then
  175. searchlist := 2;
  176. 8 : If source^.indexed Then
  177. searchlist := 4;
  178. End;
  179. { We can use a quicker loop for 8 bit }
  180. If searchlist <> $ff Then
  181. If source^.bits = 8 Then
  182. Begin
  183. For i := 0 To numConverters[searchlist] - 1 Do
  184. If standardConverters[searchlist][i] <> Nil Then
  185. If dest^.bits = standardConverters[searchlist][i]^.dest.bits Then
  186. Begin
  187. Hermes_FormatCopy(source, @cnv^.source);
  188. Hermes_FormatCopy(dest, @cnv^.dest);
  189. cnv^.loopnormal := standardConverters[searchlist][i]^.loopnormal;
  190. cnv^.loopstretch := standardConverters[searchlist][i]^.loopstretch;
  191. cnv^.normal := standardConverters[searchlist][i]^.normal;
  192. cnv^.stretch := standardConverters[searchlist][i]^.stretch;
  193. cnv^.dither := standardConverters[searchlist][i]^.dither;
  194. cnv^.ditherstretch := standardConverters[searchlist][i]^.ditherstretch;
  195. Hermes_ConverterRequest := True;
  196. Exit;
  197. End
  198. ;
  199. End
  200. Else
  201. For i := 0 To numConverters[searchlist] - 1 Do
  202. If standardConverters[searchlist][i] <> Nil Then
  203. If Hermes_FormatEquals(@standardConverters[searchlist][i]^.source, source) And
  204. Hermes_FormatEquals(@standardConverters[searchlist][i]^.dest, dest) Then
  205. Begin
  206. Hermes_FormatCopy(source, @cnv^.source);
  207. Hermes_FormatCopy(dest, @cnv^.dest);
  208. cnv^.loopnormal := standardConverters[searchlist][i]^.loopnormal;
  209. cnv^.loopstretch := standardConverters[searchlist][i]^.loopstretch;
  210. cnv^.normal := standardConverters[searchlist][i]^.normal;
  211. cnv^.stretch := standardConverters[searchlist][i]^.stretch;
  212. cnv^.dither := standardConverters[searchlist][i]^.dither;
  213. cnv^.ditherstretch := standardConverters[searchlist][i]^.ditherstretch;
  214. Hermes_ConverterRequest := True;
  215. Exit;
  216. End;
  217. { Otherwise find a generic converter }
  218. { DebugMSG('looking for a generic converter!');}
  219. cnv^.loopnormal := Nil;
  220. cnv^.loopstretch := Nil;
  221. cnv^.dither := Nil;
  222. cnv^.ditherstretch := Nil;
  223. cnv^.flags := cnv^.flags Or HERMES_CONVERT_GENERIC;
  224. { Generic routines implement whole converters not scanline converters,
  225. assign placeholders }
  226. cnv^.normal := @NotApplicable;
  227. cnv^.stretch := @NotApplicable;
  228. found := False;
  229. {
  230. Converting rules:
  231. C -> C
  232. C -> A
  233. A -> O, A -> A
  234. A -> C
  235. O -> O , A, C are the same
  236. }
  237. If source^.has_colorkey And dest^.has_colorkey Then { Ck -> Ck }
  238. Case source^.bits Of
  239. 32 : Case dest^.bits Of
  240. 32 : Begin
  241. cnv^.loopnormal := @ConvertP_Generic32_C_Generic32_C;
  242. cnv^.loopstretch := @ConvertP_Generic32_C_Generic32_C_S;
  243. found := True;
  244. End;
  245. 24 : Begin
  246. cnv^.loopnormal := @ConvertP_Generic32_C_Generic24_C;
  247. found := True;
  248. End;
  249. 16 : Begin
  250. cnv^.loopnormal := @ConvertP_Generic32_C_Generic16_C;
  251. cnv^.loopstretch := @ConvertP_Generic32_C_Generic16_C_S;
  252. found := True;
  253. End;
  254. 8 : Begin
  255. cnv^.loopnormal := @ConvertP_Generic32_C_Generic8_C;
  256. found := True;
  257. End;
  258. End;
  259. 24 : Case dest^.bits Of
  260. 32 : Begin
  261. cnv^.loopnormal := @ConvertP_Generic24_C_Generic32_C;
  262. found := True;
  263. End;
  264. 24 : Begin
  265. cnv^.loopnormal := @ConvertP_Generic24_C_Generic24_C;
  266. found := True;
  267. End;
  268. 16 : Begin
  269. cnv^.loopnormal := @ConvertP_Generic24_C_Generic16_C;
  270. found := True;
  271. End;
  272. 8 : Begin
  273. cnv^.loopnormal := @ConvertP_Generic24_C_Generic8_C;
  274. found := True;
  275. End;
  276. End;
  277. 16 : Case dest^.bits Of
  278. 32 : Begin
  279. cnv^.loopnormal := @ConvertP_Generic16_C_Generic32_C;
  280. found := True;
  281. End;
  282. 24 : Begin
  283. cnv^.loopnormal := @ConvertP_Generic16_C_Generic24_C;
  284. found := True;
  285. End;
  286. 16 : Begin
  287. cnv^.loopnormal := @ConvertP_Generic16_C_Generic16_C;
  288. found := True;
  289. End;
  290. 8 : Begin
  291. cnv^.loopnormal := @ConvertP_Generic16_C_Generic8_C;
  292. found := True;
  293. End;
  294. End;
  295. End
  296. Else
  297. If source^.has_colorkey And (dest^.a <> 0) Then { Ck -> A }
  298. Case source^.bits Of
  299. 32 : Case dest^.bits Of
  300. 32 : Begin
  301. cnv^.loopnormal := @ConvertP_Generic32_C_Generic32_A;
  302. cnv^.loopstretch := @ConvertP_Generic32_C_Generic32_A_S;
  303. found := True;
  304. End;
  305. 24 : Begin
  306. cnv^.loopnormal := @ConvertP_Generic32_C_Generic24_A;
  307. found := True;
  308. End;
  309. 16 : Begin
  310. cnv^.loopnormal := @ConvertP_Generic32_C_Generic16_A;
  311. cnv^.loopstretch := @ConvertP_Generic32_C_Generic16_A_S;
  312. found := True;
  313. End;
  314. 8 : Begin
  315. cnv^.loopnormal := @ConvertP_Generic32_C_Generic8_A;
  316. found := True;
  317. End;
  318. End;
  319. 24 : Case dest^.bits Of
  320. 32 : Begin
  321. cnv^.loopnormal := @ConvertP_Generic24_C_Generic32_A;
  322. found := True;
  323. End;
  324. 24 : Begin
  325. cnv^.loopnormal := @ConvertP_Generic24_C_Generic24_A;
  326. found := True;
  327. End;
  328. 16 : Begin
  329. cnv^.loopnormal := @ConvertP_Generic24_C_Generic16_A;
  330. found := True;
  331. End;
  332. 8 : Begin
  333. cnv^.loopnormal := @ConvertP_Generic24_C_Generic8_A;
  334. found := True;
  335. End;
  336. End;
  337. 16 : Case dest^.bits Of
  338. 32 : Begin
  339. cnv^.loopnormal := @ConvertP_Generic16_C_Generic32_A;
  340. found := True;
  341. End;
  342. 24 : Begin
  343. cnv^.loopnormal := @ConvertP_Generic16_C_Generic24_A;
  344. found := True;
  345. End;
  346. 16 : Begin
  347. cnv^.loopnormal := @ConvertP_Generic16_C_Generic16_A;
  348. found := True;
  349. End;
  350. 8 : Begin
  351. cnv^.loopnormal := @ConvertP_Generic16_C_Generic8_A;
  352. found := True;
  353. End;
  354. End;
  355. End
  356. Else
  357. If (source^.a <> 0) And dest^.has_colorkey Then { A -> Ck }
  358. Case source^.bits Of
  359. 32 : Case dest^.bits Of
  360. 32 : Begin
  361. cnv^.loopnormal := @ConvertP_Generic32_A_Generic32_C;
  362. cnv^.loopstretch := @ConvertP_Generic32_A_Generic32_C_S;
  363. found := True;
  364. End;
  365. 24 : Begin
  366. cnv^.loopnormal := @ConvertP_Generic32_A_Generic24_C;
  367. found := True;
  368. End;
  369. 16 : Begin
  370. cnv^.loopnormal := @ConvertP_Generic32_A_Generic16_C;
  371. cnv^.loopnormal := @ConvertP_Generic32_A_Generic16_C_S;
  372. found := True;
  373. End;
  374. 8 : Begin
  375. cnv^.loopnormal := @ConvertP_Generic32_A_Generic8_C;
  376. found := True;
  377. End;
  378. End;
  379. 24 : Case dest^.bits Of
  380. 32 : Begin
  381. cnv^.loopnormal := @ConvertP_Generic24_A_Generic32_C;
  382. found := True;
  383. End;
  384. 24 : Begin
  385. cnv^.loopnormal := @ConvertP_Generic24_A_Generic24_C;
  386. found := True;
  387. End;
  388. 16 : Begin
  389. cnv^.loopnormal := @ConvertP_Generic24_A_Generic16_C;
  390. found := True;
  391. End;
  392. 8 : Begin
  393. cnv^.loopnormal := @ConvertP_Generic24_A_Generic8_C;
  394. found := True;
  395. End;
  396. End;
  397. 16 : Case dest^.bits Of
  398. 32 : Begin
  399. cnv^.loopnormal := @ConvertP_Generic16_A_Generic32_C;
  400. found := True;
  401. End;
  402. 24 : Begin
  403. cnv^.loopnormal := @ConvertP_Generic16_A_Generic24_C;
  404. found := True;
  405. End;
  406. 16 : Begin
  407. cnv^.loopnormal := @ConvertP_Generic16_A_Generic16_C;
  408. found := True;
  409. End;
  410. 8 : Begin
  411. cnv^.loopnormal := @ConvertP_Generic16_A_Generic8_C;
  412. found := True;
  413. End;
  414. End;
  415. End
  416. Else
  417. If (source^.a <> 0) And (dest^.a <> 0) Then { A -> A }
  418. Case source^.bits Of
  419. 32 : Case dest^.bits Of
  420. 32 : Begin
  421. cnv^.loopnormal := @ConvertP_Generic32_A_Generic32_A;
  422. cnv^.loopstretch := @ConvertP_Generic32_A_Generic32_A_S;
  423. found := True;
  424. End;
  425. 24 : Begin
  426. cnv^.loopnormal := @ConvertP_Generic32_A_Generic24_A;
  427. found := True;
  428. End;
  429. 16 : Begin
  430. cnv^.loopnormal := @ConvertP_Generic32_A_Generic16_A;
  431. cnv^.loopstretch := @ConvertP_Generic32_A_Generic16_A_S;
  432. found := True;
  433. End;
  434. 8 : Begin
  435. cnv^.loopnormal := @ConvertP_Generic32_A_Generic8_A;
  436. found := True;
  437. End;
  438. End;
  439. 24 : Case dest^.bits Of
  440. 32 : Begin
  441. cnv^.loopnormal := @ConvertP_Generic24_A_Generic32_A;
  442. found := True;
  443. End;
  444. 24 : Begin
  445. cnv^.loopnormal := @ConvertP_Generic24_A_Generic24_A;
  446. found := True;
  447. End;
  448. 16 : Begin
  449. cnv^.loopnormal := @ConvertP_Generic24_A_Generic16_A;
  450. found := True;
  451. End;
  452. 8 : Begin
  453. cnv^.loopnormal := @ConvertP_Generic24_A_Generic8_A;
  454. found := True;
  455. End;
  456. End;
  457. 16 : Case dest^.bits Of
  458. 32 : Begin
  459. cnv^.loopnormal := @ConvertP_Generic16_A_Generic32_A;
  460. found := True;
  461. End;
  462. 24 : Begin
  463. cnv^.loopnormal := @ConvertP_Generic16_A_Generic24_A;
  464. found := True;
  465. End;
  466. 16 : Begin
  467. cnv^.loopnormal := @ConvertP_Generic16_A_Generic16_A;
  468. found := True;
  469. End;
  470. 8 : Begin
  471. cnv^.loopnormal := @ConvertP_Generic16_A_Generic8_A;
  472. found := True;
  473. End;
  474. End;
  475. End
  476. Else { O->O, O->A, A->O, Ck->O, O->Ck }
  477. Case source^.bits Of
  478. 32 : Case dest^.bits Of
  479. 32 : Begin
  480. cnv^.loopnormal := @ConvertP_Generic32_Generic32;
  481. cnv^.loopstretch := @ConvertP_Generic32_Generic32_S;
  482. found := True;
  483. End;
  484. 24 : Begin
  485. cnv^.loopnormal := @ConvertP_Generic32_Generic24;
  486. cnv^.loopstretch := @ConvertP_Generic32_Generic24_S;
  487. found := True;
  488. End;
  489. 16 : Begin
  490. cnv^.loopnormal := @ConvertP_Generic32_Generic16;
  491. cnv^.loopstretch := @ConvertP_Generic32_Generic16_S;
  492. found := True;
  493. End;
  494. 8 : Begin
  495. cnv^.loopnormal := @ConvertP_Generic32_Generic8;
  496. cnv^.loopstretch := @ConvertP_Generic32_Generic8_S;
  497. found := True;
  498. End;
  499. End;
  500. 24 : Case dest^.bits Of
  501. 32 : Begin
  502. cnv^.loopnormal := @ConvertP_Generic24_Generic32;
  503. cnv^.loopstretch := @ConvertP_Generic24_Generic32_S;
  504. found := True;
  505. End;
  506. 24 : Begin
  507. cnv^.loopnormal := @ConvertP_Generic24_Generic24;
  508. cnv^.loopstretch := @ConvertP_Generic24_Generic24_S;
  509. found := True;
  510. End;
  511. 16 : Begin
  512. cnv^.loopnormal := @ConvertP_Generic24_Generic16;
  513. cnv^.loopstretch := @ConvertP_Generic24_Generic16_S;
  514. found := True;
  515. End;
  516. 8 : Begin
  517. cnv^.loopnormal := @ConvertP_Generic24_Generic8;
  518. cnv^.loopstretch := @ConvertP_Generic24_Generic8_S;
  519. found := True;
  520. End;
  521. End;
  522. 16 : Case dest^.bits Of
  523. 32 : Begin
  524. cnv^.loopnormal := @ConvertP_Generic16_Generic32;
  525. cnv^.loopstretch := @ConvertP_Generic16_Generic32_S;
  526. found := True;
  527. End;
  528. 24 : Begin
  529. cnv^.loopnormal := @ConvertP_Generic16_Generic24;
  530. cnv^.loopstretch := @ConvertP_Generic16_Generic24_S;
  531. found := True;
  532. End;
  533. 16 : Begin
  534. cnv^.loopnormal := @ConvertP_Generic16_Generic16;
  535. cnv^.loopstretch := @ConvertP_Generic16_Generic16_S;
  536. found := True;
  537. End;
  538. 8 : Begin
  539. cnv^.loopnormal := @ConvertP_Generic16_Generic8;
  540. cnv^.loopstretch := @ConvertP_Generic16_Generic8_S;
  541. found := True;
  542. End;
  543. End;
  544. End;
  545. If found Then
  546. Begin
  547. Hermes_FormatCopy(source, @cnv^.source);
  548. Hermes_FormatCopy(dest, @cnv^.dest);
  549. Hermes_ConverterRequest := True;
  550. Exit;
  551. End;
  552. DebugMSG('no converter found!!!');
  553. { No converter found, fail }
  554. Hermes_ConverterRequest := False;
  555. End;
  556. Function Hermes_ConverterPalette(handle, sourcepal, destpal : THermesHandle) : Boolean;
  557. Begin
  558. { DebugMSG('Hermes_ConverterPalette('+C2Str(sourcepal)+','+C2Str(destpal)+')');}
  559. Hermes_ConverterPalette := False;
  560. If (handle < 0) Or (handle >= lastConverter) Then
  561. Exit;
  562. If ConverterList[handle] = Nil Then
  563. Exit;
  564. { Fail silently if not indexed colour format }
  565. If Not ConverterList[handle]^.source.indexed Then
  566. Begin
  567. ConverterList[handle]^.lookup := Nil;
  568. Hermes_ConverterPalette := True;
  569. Exit;
  570. End;
  571. ConverterList[handle]^.lookup :=
  572. Hermes_PaletteGetTable(sourcepal, @ConverterList[handle]^.dest);
  573. If ConverterList[handle]^.lookup = Nil Then
  574. Exit;
  575. Hermes_ConverterPalette := True;
  576. End;
  577. Function Hermes_ConverterCopy(handle : THermesHandle; s_pixels : Pointer;
  578. s_x, s_y, s_width, s_height, s_pitch : Integer;
  579. d_pixels : Pointer; d_x, d_y, d_width,
  580. d_height, d_pitch : Integer) : Boolean;
  581. Var
  582. cnv : PHermesConverter;
  583. iface : THermesConverterInterface;
  584. Begin
  585. Hermes_ConverterCopy := False;
  586. If (handle < 0) Or (handle >= lastConverter) Then
  587. Exit;
  588. cnv := ConverterList[handle];
  589. If cnv = Nil Then
  590. Exit;
  591. { Returns success if height or width is zero. This is debatable.. ! }
  592. If (s_width <= 0) Or (s_height <= 0) Or (d_width <= 0) Or (d_height <= 0) Then
  593. Begin
  594. Hermes_ConverterCopy := True;
  595. Exit;
  596. End;
  597. iface.s_pixels := s_pixels;
  598. iface.s_width := s_width;
  599. iface.s_height := s_height;
  600. iface.s_add := s_pitch - s_width * (cnv^.source.bits Shr 3);
  601. iface.s_pitch := s_pitch;
  602. iface.d_pixels := d_pixels;
  603. iface.d_width := d_width;
  604. iface.d_height := d_height;
  605. iface.d_add := d_pitch - d_width*(cnv^.dest.bits Shr 3);
  606. iface.d_pitch := d_pitch;
  607. Inc(iface.s_pixels, s_y * s_pitch + s_x * (cnv^.source.bits Shr 3));
  608. Inc(iface.d_pixels, d_y * d_pitch + d_x * (cnv^.dest.bits Shr 3));
  609. iface.s_has_colorkey := cnv^.source.has_colorkey;
  610. iface.d_has_colorkey := cnv^.dest.has_colorkey;
  611. iface.s_colorkey := cnv^.source.colorkey;
  612. iface.d_colorkey := cnv^.dest.colorkey;
  613. iface.lookup := cnv^.lookup;
  614. { For generic converters, do some extra setup (find shifts, etc.)
  615. TODO: Move that out of here and in the request routine ! }
  616. If (cnv^.flags And HERMES_CONVERT_GENERIC) <> 0 Then
  617. Begin
  618. Hermes_Calculate_Generic_Info(Hermes_Topbit(cnv^.source.r),
  619. Hermes_Topbit(cnv^.source.g),
  620. Hermes_Topbit(cnv^.source.b),
  621. Hermes_Topbit(cnv^.source.a),
  622. Hermes_Topbit(cnv^.dest.r),
  623. Hermes_Topbit(cnv^.dest.g),
  624. Hermes_Topbit(cnv^.dest.b),
  625. Hermes_Topbit(cnv^.dest.a),
  626. @iface.info);
  627. iface.mask_r := cnv^.dest.r;
  628. iface.mask_g := cnv^.dest.g;
  629. iface.mask_b := cnv^.dest.b;
  630. iface.mask_a := cnv^.dest.a;
  631. End;
  632. { Check for dithering. This should not be in here but in request as well }
  633. If (cnv^.flags And HERMES_CONVERT_DITHER) <> 0 Then
  634. Begin
  635. { If there is a ditherer, use it else fall back to normal }
  636. If cnv^.dither <> Nil Then
  637. cnv^.loopnormal := cnv^.dither;
  638. End;
  639. { Normal conversion }
  640. If (s_width = d_width) And (s_height = d_height) Then
  641. Begin
  642. If (cnv^.normal = Nil) Or (cnv^.loopnormal = Nil) Then
  643. Exit;
  644. { Optimization
  645. If (iface.s_add = 0) And (iface.d_add = 0) Then
  646. Begin
  647. iface.s_width := iface.s_width * s_height;
  648. iface.d_width := iface.d_width * d_height;
  649. iface.s_height := 1;
  650. iface.d_height := 1;
  651. End;}
  652. iface.func := cnv^.normal;
  653. cnv^.loopnormal(@iface);
  654. Hermes_ConverterCopy := True;
  655. Exit;
  656. End
  657. { Stretch conversion }
  658. Else
  659. Begin
  660. If (cnv^.stretch = Nil) Or (cnv^.loopstretch = Nil) Then
  661. Exit;
  662. iface.func := cnv^.stretch;
  663. cnv^.loopstretch(@iface);
  664. End;
  665. Hermes_ConverterCopy := True;
  666. End;