image_render.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816
  1. /* The GIMP -- an image manipulation program
  2. * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program 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
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. */
  18. #include "config.h"
  19. #include <stdlib.h>
  20. #include <string.h>
  21. #include <gtk/gtk.h>
  22. #include "apptypes.h"
  23. #include "appenv.h"
  24. #include "gimprc.h"
  25. #include "gximage.h"
  26. #include "image_render.h"
  27. #include "pixel_region.h"
  28. #include "scale.h"
  29. #include "tile.h" /* ick. */
  30. #include "libgimp/gimpmath.h"
  31. typedef struct _RenderInfo RenderInfo;
  32. typedef void (*RenderFunc) (RenderInfo *info);
  33. struct _RenderInfo
  34. {
  35. GDisplay *gdisp;
  36. TileManager *src_tiles;
  37. guint *alpha;
  38. guchar *scale;
  39. guchar *src;
  40. guchar *dest;
  41. int x, y;
  42. int w, h;
  43. float scalex;
  44. float scaley;
  45. int src_x, src_y;
  46. int src_bpp;
  47. int dest_bpp;
  48. int dest_bpl;
  49. int dest_width;
  50. int byte_order;
  51. };
  52. /* accelerate transparency of image scaling */
  53. guchar *blend_dark_check = NULL;
  54. guchar *blend_light_check = NULL;
  55. guchar *tile_buf = NULL;
  56. guchar *check_buf = NULL;
  57. guchar *empty_buf = NULL;
  58. guchar *temp_buf = NULL;
  59. static guint check_mod;
  60. static guint check_shift;
  61. static guint tile_shift;
  62. static guchar check_combos[6][2] =
  63. {
  64. { 204, 255 },
  65. { 102, 153 },
  66. { 0, 51 },
  67. { 255, 255 },
  68. { 127, 127 },
  69. { 0, 0 }
  70. };
  71. void
  72. render_setup (int check_type,
  73. int check_size)
  74. {
  75. int i, j;
  76. /* based on the tile size, determine the tile shift amount
  77. * (assume here that tile_height and tile_width are equal)
  78. */
  79. tile_shift = 0;
  80. while ((1 << tile_shift) < TILE_WIDTH)
  81. tile_shift++;
  82. /* allocate a buffer for arranging information from a row of tiles */
  83. if (!tile_buf)
  84. tile_buf = g_new (guchar, GXIMAGE_WIDTH * MAX_CHANNELS);
  85. if (check_type < 0 || check_type > 5)
  86. g_error ("invalid check_type argument to render_setup: %d", check_type);
  87. if (check_size < 0 || check_size > 2)
  88. g_error ("invalid check_size argument to render_setup: %d", check_size);
  89. if (!blend_dark_check)
  90. blend_dark_check = g_new (guchar, 65536);
  91. if (!blend_light_check)
  92. blend_light_check = g_new (guchar, 65536);
  93. for (i = 0; i < 256; i++)
  94. for (j = 0; j < 256; j++)
  95. {
  96. blend_dark_check [(i << 8) + j] = (guchar)
  97. ((j * i + check_combos[check_type][0] * (255 - i)) / 255);
  98. blend_light_check [(i << 8) + j] = (guchar)
  99. ((j * i + check_combos[check_type][1] * (255 - i)) / 255);
  100. }
  101. switch (check_size)
  102. {
  103. case SMALL_CHECKS:
  104. check_mod = 0x3;
  105. check_shift = 2;
  106. break;
  107. case MEDIUM_CHECKS:
  108. check_mod = 0x7;
  109. check_shift = 3;
  110. break;
  111. case LARGE_CHECKS:
  112. check_mod = 0xf;
  113. check_shift = 4;
  114. break;
  115. }
  116. /* calculate check buffer for previews */
  117. if (preview_size)
  118. {
  119. if (check_buf)
  120. g_free (check_buf);
  121. if (empty_buf)
  122. g_free (empty_buf);
  123. if (temp_buf)
  124. g_free (temp_buf);
  125. check_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
  126. for (i = 0; i < (preview_size + 4); i++)
  127. {
  128. if (i & 0x4)
  129. {
  130. check_buf[i * 3 + 0] = blend_dark_check[0];
  131. check_buf[i * 3 + 1] = blend_dark_check[0];
  132. check_buf[i * 3 + 2] = blend_dark_check[0];
  133. }
  134. else
  135. {
  136. check_buf[i * 3 + 0] = blend_light_check[0];
  137. check_buf[i * 3 + 1] = blend_light_check[0];
  138. check_buf[i * 3 + 2] = blend_light_check[0];
  139. }
  140. }
  141. empty_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
  142. memset (empty_buf, 0, (preview_size + 4) * 3);
  143. temp_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
  144. }
  145. else
  146. {
  147. check_buf = NULL;
  148. empty_buf = NULL;
  149. temp_buf = NULL;
  150. }
  151. }
  152. void
  153. render_free (void)
  154. {
  155. g_free (tile_buf);
  156. g_free (check_buf);
  157. }
  158. /* Render Image functions */
  159. static void render_image_rgb (RenderInfo *info);
  160. static void render_image_rgb_a (RenderInfo *info);
  161. static void render_image_gray (RenderInfo *info);
  162. static void render_image_gray_a (RenderInfo *info);
  163. static void render_image_indexed (RenderInfo *info);
  164. static void render_image_indexed_a (RenderInfo *info);
  165. static void render_image_init_info (RenderInfo *info,
  166. GDisplay *gdisp,
  167. int x,
  168. int y,
  169. int w,
  170. int h);
  171. static guint* render_image_init_alpha (int mult);
  172. static guchar* render_image_accelerate_scaling (int width,
  173. int start,
  174. float scalex);
  175. static guchar* render_image_tile_fault (RenderInfo *info);
  176. static RenderFunc render_funcs[6] =
  177. {
  178. render_image_rgb,
  179. render_image_rgb_a,
  180. render_image_gray,
  181. render_image_gray_a,
  182. render_image_indexed,
  183. render_image_indexed_a,
  184. };
  185. /*****************************************************************/
  186. /* This function is the core of the display--it offsets and */
  187. /* scales the image according to the current parameters in the */
  188. /* gdisp object. It handles color, grayscale, 8, 15, 16, 24, */
  189. /* & 32 bit output depths. */
  190. /*****************************************************************/
  191. void
  192. render_image (GDisplay *gdisp,
  193. int x,
  194. int y,
  195. int w,
  196. int h)
  197. {
  198. RenderInfo info;
  199. int image_type;
  200. render_image_init_info (&info, gdisp, x, y, w, h);
  201. image_type = gimage_projection_type (gdisp->gimage);
  202. if ((image_type < 0) || (image_type > 5))
  203. {
  204. g_message ("unknown gimage projection type: %d",
  205. gimage_projection_type (gdisp->gimage));
  206. return;
  207. }
  208. if ((info.dest_bpp < 1) || (info.dest_bpp > 4))
  209. {
  210. g_message ("unsupported destination bytes per pixel: %d", info.dest_bpp);
  211. return;
  212. }
  213. /* Currently, only RGBA and GRAYA projection types are used - the rest
  214. * are in case of future need. -- austin, 28th Nov 1998. */
  215. if (image_type != RGBA_GIMAGE && image_type != GRAYA_GIMAGE)
  216. g_warning ("using untested projection type %d", image_type);
  217. (* render_funcs[image_type]) (&info);
  218. }
  219. /*************************/
  220. /* 8 Bit functions */
  221. /*************************/
  222. static void
  223. render_image_indexed (RenderInfo *info)
  224. {
  225. guchar *src;
  226. guchar *dest;
  227. guchar *cmap;
  228. gulong val;
  229. gint byte_order;
  230. gint y, ye;
  231. gint x, xe;
  232. gint initial;
  233. cmap = gimage_cmap (info->gdisp->gimage);
  234. y = info->y;
  235. ye = info->y + info->h;
  236. xe = info->x + info->w;
  237. initial = TRUE;
  238. byte_order = info->byte_order;
  239. info->src = render_image_tile_fault (info);
  240. for (; y < ye; y++)
  241. {
  242. gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  243. if (!initial && (error == 0))
  244. memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  245. else
  246. {
  247. src = info->src;
  248. dest = info->dest;
  249. g_return_if_fail (src != NULL);
  250. for (x = info->x; x < xe; x++)
  251. {
  252. val = src[INDEXED_PIX] * 3;
  253. src += 1;
  254. dest[0] = cmap[val+0];
  255. dest[1] = cmap[val+1];
  256. dest[2] = cmap[val+2];
  257. dest += 3;
  258. }
  259. }
  260. info->dest += info->dest_bpl;
  261. initial = FALSE;
  262. if (error >= 1)
  263. {
  264. info->src_y += error;
  265. info->src = render_image_tile_fault (info);
  266. initial = TRUE;
  267. }
  268. }
  269. }
  270. static void
  271. render_image_indexed_a (RenderInfo *info)
  272. {
  273. guchar *src;
  274. guchar *dest;
  275. guint *alpha;
  276. guchar *cmap;
  277. gulong r, g, b;
  278. gulong val;
  279. guint a;
  280. gint dark_light;
  281. gint byte_order;
  282. gint y, ye;
  283. gint x, xe;
  284. gint initial;
  285. cmap = gimage_cmap (info->gdisp->gimage);
  286. alpha = info->alpha;
  287. y = info->y;
  288. ye = info->y + info->h;
  289. xe = info->x + info->w;
  290. initial = TRUE;
  291. byte_order = info->byte_order;
  292. info->src = render_image_tile_fault (info);
  293. for (; y < ye; y++)
  294. {
  295. gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  296. if (!initial && (error == 0) && (y & check_mod))
  297. memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  298. else
  299. {
  300. src = info->src;
  301. dest = info->dest;
  302. dark_light = (y >> check_shift) + (info->x >> check_shift);
  303. g_return_if_fail (src != NULL);
  304. for (x = info->x; x < xe; x++)
  305. {
  306. a = alpha[src[ALPHA_I_PIX]];
  307. val = src[INDEXED_PIX] * 3;
  308. src += 2;
  309. if (dark_light & 0x1)
  310. {
  311. r = blend_dark_check[(a | cmap[val+0])];
  312. g = blend_dark_check[(a | cmap[val+1])];
  313. b = blend_dark_check[(a | cmap[val+2])];
  314. }
  315. else
  316. {
  317. r = blend_light_check[(a | cmap[val+0])];
  318. g = blend_light_check[(a | cmap[val+1])];
  319. b = blend_light_check[(a | cmap[val+2])];
  320. }
  321. dest[0] = r;
  322. dest[1] = g;
  323. dest[2] = b;
  324. dest += 3;
  325. if (((x + 1) & check_mod) == 0)
  326. dark_light += 1;
  327. }
  328. }
  329. info->dest += info->dest_bpl;
  330. initial = FALSE;
  331. if (error >= 1)
  332. {
  333. info->src_y += error;
  334. info->src = render_image_tile_fault (info);
  335. initial = TRUE;
  336. }
  337. }
  338. }
  339. static void
  340. render_image_gray (RenderInfo *info)
  341. {
  342. guchar *src;
  343. guchar *dest;
  344. gulong val;
  345. gint byte_order;
  346. gint y, ye;
  347. gint x, xe;
  348. gint initial;
  349. y = info->y;
  350. ye = info->y + info->h;
  351. xe = info->x + info->w;
  352. initial = TRUE;
  353. byte_order = info->byte_order;
  354. info->src = render_image_tile_fault (info);
  355. for (; y < ye; y++)
  356. {
  357. gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  358. if (!initial && (error == 0))
  359. memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  360. else
  361. {
  362. src = info->src;
  363. dest = info->dest;
  364. g_return_if_fail (src != NULL);
  365. for (x = info->x; x < xe; x++)
  366. {
  367. val = src[GRAY_PIX];
  368. src += 1;
  369. dest[0] = val;
  370. dest[1] = val;
  371. dest[2] = val;
  372. dest += 3;
  373. }
  374. }
  375. info->dest += info->dest_bpl;
  376. initial = FALSE;
  377. if (error >= 1)
  378. {
  379. info->src_y += error;
  380. info->src = render_image_tile_fault (info);
  381. initial = TRUE;
  382. }
  383. }
  384. }
  385. static void
  386. render_image_gray_a (RenderInfo *info)
  387. {
  388. guchar *src;
  389. guchar *dest;
  390. guint *alpha;
  391. gulong val;
  392. guint a;
  393. gint dark_light;
  394. gint byte_order;
  395. gint y, ye;
  396. gint x, xe;
  397. gint initial;
  398. alpha = info->alpha;
  399. y = info->y;
  400. ye = info->y + info->h;
  401. xe = info->x + info->w;
  402. initial = TRUE;
  403. byte_order = info->byte_order;
  404. info->src = render_image_tile_fault (info);
  405. for (; y < ye; y++)
  406. {
  407. gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  408. if (!initial && (error == 0) && (y & check_mod))
  409. memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  410. else
  411. {
  412. src = info->src;
  413. dest = info->dest;
  414. dark_light = (y >> check_shift) + (info->x >> check_shift);
  415. g_return_if_fail (src != NULL);
  416. for (x = info->x; x < xe; x++)
  417. {
  418. a = alpha[src[ALPHA_G_PIX]];
  419. if (dark_light & 0x1)
  420. val = blend_dark_check[(a | src[GRAY_PIX])];
  421. else
  422. val = blend_light_check[(a | src[GRAY_PIX])];
  423. src += 2;
  424. dest[0] = val;
  425. dest[1] = val;
  426. dest[2] = val;
  427. dest += 3;
  428. if (((x + 1) & check_mod) == 0)
  429. dark_light += 1;
  430. }
  431. }
  432. info->dest += info->dest_bpl;
  433. initial = FALSE;
  434. if (error >= 1)
  435. {
  436. info->src_y += error;
  437. info->src = render_image_tile_fault (info);
  438. initial = TRUE;
  439. }
  440. }
  441. }
  442. static void
  443. render_image_rgb (RenderInfo *info)
  444. {
  445. guchar *src;
  446. guchar *dest;
  447. gint byte_order;
  448. gint y, ye;
  449. gint x, xe;
  450. gint initial;
  451. y = info->y;
  452. ye = info->y + info->h;
  453. xe = info->x + info->w;
  454. initial = TRUE;
  455. byte_order = info->byte_order;
  456. info->src = render_image_tile_fault (info);
  457. for (; y < ye; y++)
  458. {
  459. gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  460. if (!initial && (error == 0))
  461. memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  462. else
  463. {
  464. src = info->src;
  465. dest = info->dest;
  466. g_return_if_fail (src != NULL);
  467. /* replace this with memcpy, or better yet, avoid it altogether? */
  468. for (x = info->x; x < xe; x++)
  469. {
  470. dest[0] = src[0];
  471. dest[1] = src[1];
  472. dest[2] = src[2];
  473. src += 3;
  474. dest += 3;
  475. }
  476. }
  477. info->dest += info->dest_bpl;
  478. initial = FALSE;
  479. if (error >= 1)
  480. {
  481. info->src_y += error;
  482. info->src = render_image_tile_fault (info);
  483. initial = TRUE;
  484. }
  485. }
  486. }
  487. static void
  488. render_image_rgb_a (RenderInfo *info)
  489. {
  490. guchar *src;
  491. guchar *dest;
  492. guint *alpha;
  493. gulong r, g, b;
  494. guint a;
  495. gint dark_light;
  496. gint byte_order;
  497. gint y, ye;
  498. gint x, xe;
  499. gint initial;
  500. alpha = info->alpha;
  501. y = info->y;
  502. ye = info->y + info->h;
  503. xe = info->x + info->w;
  504. initial = TRUE;
  505. byte_order = info->byte_order;
  506. info->src = render_image_tile_fault (info);
  507. for (; y < ye; y++)
  508. {
  509. gint error = floor ((y + 1) / info->scaley) - floor (y / info->scaley);
  510. if (!initial && (error == 0) && (y & check_mod))
  511. memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  512. else
  513. {
  514. src = info->src;
  515. dest = info->dest;
  516. dark_light = (y >> check_shift) + (info->x >> check_shift);
  517. g_return_if_fail (src != NULL);
  518. for (x = info->x; x < xe; x++)
  519. {
  520. a = alpha[src[ALPHA_PIX]];
  521. if (dark_light & 0x1)
  522. {
  523. r = blend_dark_check[(a | src[RED_PIX])];
  524. g = blend_dark_check[(a | src[GREEN_PIX])];
  525. b = blend_dark_check[(a | src[BLUE_PIX])];
  526. }
  527. else
  528. {
  529. r = blend_light_check[(a | src[RED_PIX])];
  530. g = blend_light_check[(a | src[GREEN_PIX])];
  531. b = blend_light_check[(a | src[BLUE_PIX])];
  532. }
  533. src += 4;
  534. dest[0] = r;
  535. dest[1] = g;
  536. dest[2] = b;
  537. dest += 3;
  538. if (((x + 1) & check_mod) == 0)
  539. dark_light += 1;
  540. }
  541. }
  542. info->dest += info->dest_bpl;
  543. initial = FALSE;
  544. if (error >= 1)
  545. {
  546. info->src_y += error;
  547. info->src = render_image_tile_fault (info);
  548. initial = TRUE;
  549. }
  550. }
  551. }
  552. static void
  553. render_image_init_info (RenderInfo *info,
  554. GDisplay *gdisp,
  555. int x,
  556. int y,
  557. int w,
  558. int h)
  559. {
  560. info->gdisp = gdisp;
  561. info->src_tiles = gimage_projection (gdisp->gimage);
  562. info->x = x + gdisp->offset_x;
  563. info->y = y + gdisp->offset_y;
  564. info->w = w;
  565. info->h = h;
  566. info->scalex = SCALEFACTOR_X (gdisp);
  567. info->scaley = SCALEFACTOR_Y (gdisp);
  568. info->src_x = UNSCALEX (gdisp, info->x);
  569. info->src_y = UNSCALEY (gdisp, info->y);
  570. info->src_bpp = gimage_projection_bytes (gdisp->gimage);
  571. info->dest = gximage_get_data ();
  572. info->dest_bpp = gximage_get_bpp ();
  573. info->dest_bpl = gximage_get_bpl ();
  574. info->dest_width = info->w * info->dest_bpp;
  575. info->byte_order = gximage_get_byte_order ();
  576. info->scale = render_image_accelerate_scaling (w, info->x, info->scalex);
  577. info->alpha = NULL;
  578. switch (gimage_projection_type (gdisp->gimage))
  579. {
  580. case RGBA_GIMAGE:
  581. case GRAYA_GIMAGE:
  582. case INDEXEDA_GIMAGE:
  583. info->alpha = render_image_init_alpha (gimage_projection_opacity (gdisp->gimage));
  584. break;
  585. default:
  586. /* nothing special needs doing */
  587. break;
  588. }
  589. }
  590. static guint*
  591. render_image_init_alpha (int mult)
  592. {
  593. static guint *alpha_mult = NULL;
  594. static int alpha_val = -1;
  595. int i;
  596. if (alpha_val != mult)
  597. {
  598. if (!alpha_mult)
  599. alpha_mult = g_new (guint, 256);
  600. alpha_val = mult;
  601. for (i = 0; i < 256; i++)
  602. alpha_mult[i] = ((mult * i) / 255) << 8;
  603. }
  604. return alpha_mult;
  605. }
  606. static guchar*
  607. render_image_accelerate_scaling (int width,
  608. int start,
  609. float scalex)
  610. {
  611. static guchar *scale = NULL;
  612. gint i;
  613. if (!scale)
  614. scale = g_new (guchar, GXIMAGE_WIDTH + 1);
  615. for (i = 0; i <= width; i++)
  616. {
  617. scale[i] = floor ((start + 1) / scalex) - floor (start / scalex);
  618. start++;
  619. }
  620. return scale;
  621. }
  622. static guchar*
  623. render_image_tile_fault (RenderInfo *info)
  624. {
  625. Tile *tile;
  626. guchar *data;
  627. guchar *dest;
  628. guchar *scale;
  629. int width;
  630. int tilex;
  631. int tiley;
  632. int srctilex, srctiley;
  633. int step;
  634. int bpp = info->src_bpp;
  635. int x, b;
  636. tilex = info->src_x / TILE_WIDTH;
  637. tiley = info->src_y / TILE_HEIGHT;
  638. tile = tile_manager_get_tile (info->src_tiles,
  639. srctilex=info->src_x, srctiley=info->src_y,
  640. TRUE, FALSE);
  641. if (!tile)
  642. return NULL;
  643. data = tile_data_pointer (tile,
  644. info->src_x % TILE_WIDTH,
  645. info->src_y % TILE_HEIGHT);
  646. scale = info->scale;
  647. dest = tile_buf;
  648. x = info->src_x;
  649. width = info->w;
  650. while (width--)
  651. {
  652. for (b = 0; b < bpp; b++)
  653. *dest++ = data[b];
  654. step = *scale++;
  655. if (step != 0)
  656. {
  657. x += step;
  658. data += step * bpp;
  659. if ((x >> tile_shift) != tilex)
  660. {
  661. tile_release (tile, FALSE);
  662. tilex += 1;
  663. tile = tile_manager_get_tile (info->src_tiles, srctilex=x,
  664. srctiley=info->src_y, TRUE, FALSE);
  665. if (!tile)
  666. return tile_buf;
  667. data = tile_data_pointer (tile,
  668. x % TILE_WIDTH,
  669. info->src_y % TILE_HEIGHT);
  670. }
  671. }
  672. }
  673. tile_release (tile, FALSE);
  674. return tile_buf;
  675. }