home *** CD-ROM | disk | FTP | other *** search
/ PC Pro 2002 April / pcpro0402.iso / essentials / graphics / Gimp / gimp-src-20001226.exe / src / gimp / app / image_render.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-12-17  |  18.6 KB  |  870 lines

  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.  
  19. #include "config.h"
  20.  
  21. #include <stdlib.h>
  22. #include <string.h>
  23.  
  24. #include <gtk/gtk.h>
  25.  
  26. #include "apptypes.h"
  27.  
  28. #include "appenv.h"
  29. #include "gimprc.h"
  30. #include "gximage.h"
  31. #include "image_render.h"
  32. #include "pixel_region.h"
  33. #include "scale.h"
  34.  
  35. #include "tile.h"            /* ick. */
  36.  
  37. typedef struct _RenderInfo  RenderInfo;
  38. typedef void (*RenderFunc) (RenderInfo *info);
  39.  
  40. struct _RenderInfo
  41. {
  42.   GDisplay *gdisp;
  43.   TileManager *src_tiles;
  44.   guint *alpha;
  45.   guchar *scale;
  46.   guchar *src;
  47.   guchar *dest;
  48.   int x, y;
  49.   int w, h;
  50.   float scalex;
  51.   float scaley;
  52.   int src_x, src_y;
  53.   int src_bpp;
  54.   int dest_bpp;
  55.   int dest_bpl;
  56.   int dest_width;
  57.   int byte_order;
  58. };
  59.  
  60.  
  61. /*  accelerate transparency of image scaling  */
  62. guchar *blend_dark_check = NULL;
  63. guchar *blend_light_check = NULL;
  64. guchar *tile_buf = NULL;
  65. guchar *check_buf = NULL;
  66. guchar *empty_buf = NULL;
  67. guchar *temp_buf = NULL;
  68.  
  69. static guint   check_mod;
  70. static guint   check_shift;
  71. static guint   tile_shift;
  72. static guchar  check_combos[6][2] =
  73. {
  74.   { 204, 255 },
  75.   { 102, 153 },
  76.   { 0, 51 },
  77.   { 255, 255 },
  78.   { 127, 127 },
  79.   { 0, 0 }
  80. };
  81.  
  82.  
  83.  
  84. void
  85. render_setup (int check_type,
  86.           int check_size)
  87. {
  88.   int i, j;
  89.  
  90.   /*  based on the tile size, determine the tile shift amount
  91.    *  (assume here that tile_height and tile_width are equal)
  92.    */
  93.   tile_shift = 0;
  94.   while ((1 << tile_shift) < TILE_WIDTH)
  95.     tile_shift++;
  96.  
  97.   /*  allocate a buffer for arranging information from a row of tiles  */
  98.   if (!tile_buf)
  99.     tile_buf = g_new (guchar, GXIMAGE_WIDTH * MAX_CHANNELS);
  100.  
  101.   if (check_type < 0 || check_type > 5)
  102.     g_error ("invalid check_type argument to render_setup: %d", check_type);
  103.   if (check_size < 0 || check_size > 2)
  104.     g_error ("invalid check_size argument to render_setup: %d", check_size);
  105.  
  106.   if (!blend_dark_check)
  107.     blend_dark_check = g_new (guchar, 65536);
  108.   if (!blend_light_check)
  109.     blend_light_check = g_new (guchar, 65536);
  110.  
  111.   for (i = 0; i < 256; i++)
  112.     for (j = 0; j < 256; j++)
  113.       {
  114.     blend_dark_check [(i << 8) + j] = (guchar)
  115.       ((j * i + check_combos[check_type][0] * (255 - i)) / 255);
  116.     blend_light_check [(i << 8) + j] = (guchar)
  117.       ((j * i + check_combos[check_type][1] * (255 - i)) / 255);
  118.       }
  119.  
  120.   switch (check_size)
  121.     {
  122.     case SMALL_CHECKS:
  123.       check_mod = 0x3;
  124.       check_shift = 2;
  125.       break;
  126.     case MEDIUM_CHECKS:
  127.       check_mod = 0x7;
  128.       check_shift = 3;
  129.       break;
  130.     case LARGE_CHECKS:
  131.       check_mod = 0xf;
  132.       check_shift = 4;
  133.       break;
  134.     }
  135.  
  136.   /*  calculate check buffer for previews  */
  137.   if (preview_size)
  138.     {
  139.       if (check_buf)
  140.     g_free (check_buf);
  141.       if (empty_buf)
  142.     g_free (empty_buf);
  143.       if (temp_buf)
  144.     g_free (temp_buf);
  145.  
  146.       check_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
  147.       for (i = 0; i < (preview_size + 4); i++)
  148.     {
  149.       if (i & 0x4)
  150.         {
  151.           check_buf[i * 3 + 0] = blend_dark_check[0];
  152.           check_buf[i * 3 + 1] = blend_dark_check[0];
  153.           check_buf[i * 3 + 2] = blend_dark_check[0];
  154.         }
  155.       else
  156.         {
  157.           check_buf[i * 3 + 0] = blend_light_check[0];
  158.           check_buf[i * 3 + 1] = blend_light_check[0];
  159.           check_buf[i * 3 + 2] = blend_light_check[0];
  160.         }
  161.     }
  162.       empty_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
  163.       memset (empty_buf, 0, (preview_size + 4) * 3);
  164.       temp_buf = (unsigned char *) g_malloc ((preview_size + 4) * 3);
  165.     }
  166.   else
  167.     {
  168.       check_buf = NULL;
  169.       empty_buf = NULL;
  170.       temp_buf = NULL;
  171.     }
  172. }
  173.  
  174. void
  175. render_free (void)
  176. {
  177.   g_free (tile_buf);
  178.   g_free (check_buf);
  179. }
  180.  
  181. /*  Render Image functions  */
  182.  
  183. static void    render_image_rgb       (RenderInfo *info);
  184. static void    render_image_rgb_a     (RenderInfo *info);
  185. static void    render_image_gray      (RenderInfo *info);
  186. static void    render_image_gray_a    (RenderInfo *info);
  187. static void    render_image_indexed   (RenderInfo *info);
  188. static void    render_image_indexed_a (RenderInfo *info);
  189.  
  190. static void    render_image_init_info          (RenderInfo   *info,
  191.                         GDisplay     *gdisp,
  192.                         int           x,
  193.                         int           y,
  194.                         int           w,
  195.                         int           h);
  196. static guint*  render_image_init_alpha         (int           mult);
  197. static guchar* render_image_accelerate_scaling (int           width,
  198.                         int           start,
  199.                         float         scalex);
  200. static guchar* render_image_tile_fault         (RenderInfo   *info);
  201.  
  202.  
  203. static RenderFunc render_funcs[6] =
  204. {
  205.     render_image_rgb,
  206.     render_image_rgb_a,
  207.     render_image_gray,
  208.     render_image_gray_a,
  209.     render_image_indexed,
  210.     render_image_indexed_a,
  211. };
  212.  
  213.  
  214. /*****************************************************************/
  215. /*  This function is the core of the display--it offsets and     */
  216. /*  scales the image according to the current parameters in the  */
  217. /*  gdisp object.  It handles color, grayscale, 8, 15, 16, 24,   */
  218. /*  & 32 bit output depths.                                      */
  219. /*****************************************************************/
  220.  
  221. void
  222. render_image (GDisplay *gdisp,
  223.           int       x,
  224.           int       y,
  225.           int       w,
  226.           int       h)
  227. {
  228.   RenderInfo info;
  229.   int image_type;
  230.  
  231.   render_image_init_info (&info, gdisp, x, y, w, h);
  232.  
  233.   image_type = gimage_projection_type (gdisp->gimage);
  234.   if ((image_type < 0) || (image_type > 5))
  235.     {
  236.       g_message ("unknown gimage projection type: %d",
  237.          gimage_projection_type (gdisp->gimage));
  238.       return;
  239.     }
  240.  
  241.   if ((info.dest_bpp < 1) || (info.dest_bpp > 4))
  242.     {
  243.       g_message ("unsupported destination bytes per pixel: %d", info.dest_bpp);
  244.       return;
  245.     }
  246.  
  247.   /* Currently, only RGBA and GRAYA projection types are used - the rest
  248.    * are in case of future need.  -- austin, 28th Nov 1998. */
  249.   if (image_type != RGBA_GIMAGE && image_type != GRAYA_GIMAGE)
  250.       g_warning ("using untested projection type %d", image_type);
  251.  
  252.   (* render_funcs[image_type]) (&info);
  253. }
  254.  
  255.  
  256.  
  257. /*************************/
  258. /*  8 Bit functions      */
  259. /*************************/
  260.  
  261. static void
  262. render_image_indexed (RenderInfo *info)
  263. {
  264.   guchar *src;
  265.   guchar *dest;
  266.   guchar *cmap;
  267.   gulong val;
  268.   int byte_order;
  269.   int y, ye;
  270.   int x, xe;
  271.   int initial;
  272.   float error;
  273.   float step;
  274.  
  275.   cmap = gimage_cmap (info->gdisp->gimage);
  276.  
  277.   y = info->y;
  278.   ye = info->y + info->h;
  279.   xe = info->x + info->w;
  280.  
  281.   step = 1.0 / info->scaley;
  282.  
  283.   error = y * step;
  284.   error -= ((int)error) - step;
  285.  
  286.   initial = TRUE;
  287.   byte_order = info->byte_order;
  288.   info->src = render_image_tile_fault (info);
  289.  
  290.   for (; y < ye; y++)
  291.     {
  292.       if (!initial && (error < 1.0))
  293.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  294.       else
  295.     {
  296.       src = info->src;
  297.       dest = info->dest;
  298.  
  299.       g_return_if_fail (src != NULL);
  300.       
  301.       for (x = info->x; x < xe; x++)
  302.         {
  303.           val = src[INDEXED_PIX] * 3;
  304.           src += 1;
  305.  
  306.           dest[0] = cmap[val+0];
  307.           dest[1] = cmap[val+1];
  308.           dest[2] = cmap[val+2];
  309.           dest += 3;
  310.         }
  311.     }
  312.  
  313.       info->dest += info->dest_bpl;
  314.  
  315.       initial = FALSE;
  316.  
  317.       if (error >= 1.0)
  318.     {
  319.       info->src_y += (int)error;
  320.       error -= (int)error;
  321.       info->src = render_image_tile_fault (info);
  322.       initial = TRUE;
  323.     }
  324.  
  325.       error += step;
  326.     }
  327. }
  328.  
  329. static void
  330. render_image_indexed_a (RenderInfo *info)
  331. {
  332.   guchar *src;
  333.   guchar *dest;
  334.   guint *alpha;
  335.   guchar *cmap;
  336.   gulong r, g, b;
  337.   gulong val;
  338.   guint a;
  339.   int dark_light;
  340.   int byte_order;
  341.   int y, ye;
  342.   int x, xe;
  343.   int initial;
  344.   float error;
  345.   float step;
  346.  
  347.   cmap = gimage_cmap (info->gdisp->gimage);
  348.   alpha = info->alpha;
  349.  
  350.   y = info->y;
  351.   ye = info->y + info->h;
  352.   xe = info->x + info->w;
  353.  
  354.   step = 1.0 / info->scaley;
  355.  
  356.   error = y * step;
  357.   error -= ((int)error) - step;
  358.  
  359.   initial = TRUE;
  360.   byte_order = info->byte_order;
  361.   info->src = render_image_tile_fault (info);
  362.  
  363.   for (; y < ye; y++)
  364.     {
  365.       if (!initial && (error < 1.0) && (y & check_mod))
  366.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  367.       else
  368.     {
  369.       src = info->src;
  370.       dest = info->dest;
  371.  
  372.       dark_light = (y >> check_shift) + (info->x >> check_shift);
  373.  
  374.       g_return_if_fail (src != NULL);
  375.  
  376.       for (x = info->x; x < xe; x++)
  377.         {
  378.           a = alpha[src[ALPHA_I_PIX]];
  379.           val = src[INDEXED_PIX] * 3;
  380.           src += 2;
  381.  
  382.           if (dark_light & 0x1)
  383.         {
  384.           r = blend_dark_check[(a | cmap[val+0])];
  385.           g = blend_dark_check[(a | cmap[val+1])];
  386.           b = blend_dark_check[(a | cmap[val+2])];
  387.         }
  388.           else
  389.         {
  390.           r = blend_light_check[(a | cmap[val+0])];
  391.           g = blend_light_check[(a | cmap[val+1])];
  392.           b = blend_light_check[(a | cmap[val+2])];
  393.         }
  394.  
  395.         dest[0] = r;
  396.         dest[1] = g;
  397.         dest[2] = b;
  398.         dest += 3;
  399.  
  400.         if (((x + 1) & check_mod) == 0)
  401.           dark_light += 1;
  402.           }
  403.     }
  404.  
  405.       info->dest += info->dest_bpl;
  406.  
  407.       initial = FALSE;
  408.  
  409.       if (error >= 1.0)
  410.     {
  411.       info->src_y += (int)error;
  412.       error -= (int)error;
  413.       info->src = render_image_tile_fault (info);
  414.       initial = TRUE;
  415.     }
  416.  
  417.       error += step;
  418.     }
  419. }
  420.  
  421. static void
  422. render_image_gray (RenderInfo *info)
  423. {
  424.   guchar *src;
  425.   guchar *dest;
  426.   gulong val;
  427.   int byte_order;
  428.   int y, ye;
  429.   int x, xe;
  430.   int initial;
  431.   float error;
  432.   float step;
  433.  
  434.   y = info->y;
  435.   ye = info->y + info->h;
  436.   xe = info->x + info->w;
  437.  
  438.   step = 1.0 / info->scaley;
  439.  
  440.   error = y * step;
  441.   error -= ((int)error) - step;
  442.  
  443.   initial = TRUE;
  444.   byte_order = info->byte_order;
  445.   info->src = render_image_tile_fault (info);
  446.  
  447.   for (; y < ye; y++)
  448.     {
  449.       if (!initial && (error < 1.0))
  450.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  451.       else
  452.     {
  453.       src = info->src;
  454.       dest = info->dest;
  455.       
  456.       g_return_if_fail (src != NULL);
  457.  
  458.       for (x = info->x; x < xe; x++)
  459.         {
  460.           val = src[GRAY_PIX];
  461.           src += 1;
  462.  
  463.           dest[0] = val;
  464.           dest[1] = val;
  465.           dest[2] = val;
  466.           dest += 3;
  467.         }
  468.     }
  469.  
  470.       info->dest += info->dest_bpl;
  471.  
  472.       initial = FALSE;
  473.  
  474.       if (error >= 1.0)
  475.     {
  476.       info->src_y += (int)error;
  477.       error -= (int)error;
  478.       info->src = render_image_tile_fault (info);
  479.       initial = TRUE;
  480.     }
  481.  
  482.       error += step;
  483.     }
  484. }
  485.  
  486. static void
  487. render_image_gray_a (RenderInfo *info)
  488. {
  489.   guchar *src;
  490.   guchar *dest;
  491.   guint *alpha;
  492.   gulong val;
  493.   guint a;
  494.   int dark_light;
  495.   int byte_order;
  496.   int y, ye;
  497.   int x, xe;
  498.   int initial;
  499.   float error;
  500.   float step;
  501.  
  502.   alpha = info->alpha;
  503.  
  504.   y = info->y;
  505.   ye = info->y + info->h;
  506.   xe = info->x + info->w;
  507.  
  508.   step = 1.0 / info->scaley;
  509.  
  510.   error = y * step;
  511.   error -= ((int)error) - step;
  512.  
  513.   initial = TRUE;
  514.   byte_order = info->byte_order;
  515.   info->src = render_image_tile_fault (info);
  516.  
  517.   for (; y < ye; y++)
  518.     {
  519.       if (!initial && (error < 1.0) && (y & check_mod))
  520.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  521.       else
  522.     {
  523.       src = info->src;
  524.       dest = info->dest;
  525.  
  526.       dark_light = (y >> check_shift) + (info->x >> check_shift);
  527.  
  528.       g_return_if_fail (src != NULL);
  529.  
  530.       for (x = info->x; x < xe; x++)
  531.         {
  532.           a = alpha[src[ALPHA_G_PIX]];
  533.           if (dark_light & 0x1)
  534.         val = blend_dark_check[(a | src[GRAY_PIX])];
  535.           else
  536.         val = blend_light_check[(a | src[GRAY_PIX])];
  537.           src += 2;
  538.  
  539.           dest[0] = val;
  540.           dest[1] = val;
  541.           dest[2] = val;
  542.           dest += 3;
  543.  
  544.           if (((x + 1) & check_mod) == 0)
  545.         dark_light += 1;
  546.         }
  547.     }
  548.  
  549.       info->dest += info->dest_bpl;
  550.  
  551.       initial = FALSE;
  552.  
  553.       if (error >= 1.0)
  554.     {
  555.       info->src_y += (int)error;
  556.       error -= (int)error;
  557.       info->src = render_image_tile_fault (info);
  558.       initial = TRUE;
  559.     }
  560.  
  561.       error += step;
  562.     }
  563. }
  564.  
  565. static void
  566. render_image_rgb (RenderInfo *info)
  567. {
  568.   guchar *src;
  569.   guchar *dest;
  570.   int byte_order;
  571.   int y, ye;
  572.   int x, xe;
  573.   int initial;
  574.   float error;
  575.   float step;
  576.  
  577.   y = info->y;
  578.   ye = info->y + info->h;
  579.   xe = info->x + info->w;
  580.  
  581.   step = 1.0 / info->scaley;
  582.  
  583.   error = y * step;
  584.   error -= (int)error - step;
  585.  
  586.   initial = TRUE;
  587.   byte_order = info->byte_order;
  588.   info->src = render_image_tile_fault (info);
  589.  
  590.   for (; y < ye; y++)
  591.     {
  592.       if (!initial && (error < 1.0))
  593.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  594.       else
  595.     {
  596.       src = info->src;
  597.       dest = info->dest;
  598.  
  599.       g_return_if_fail (src != NULL);
  600.       
  601.       /* replace this with memcpy, or better yet, avoid it altogether? */
  602.       for (x = info->x; x < xe; x++)
  603.         {
  604.           dest[0] = src[0];
  605.           dest[1] = src[1];
  606.           dest[2] = src[2];
  607.  
  608.           src += 3;
  609.           dest += 3;
  610.         }
  611.     }
  612.  
  613.       info->dest += info->dest_bpl;
  614.  
  615.       initial = FALSE;
  616.  
  617.       if (error >= 1.0)
  618.     {
  619.       info->src_y += (int)error;
  620.       error -= (int)error;
  621.       info->src = render_image_tile_fault (info);
  622.       initial = TRUE;
  623.     }
  624.  
  625.       error += step;
  626.     }
  627. }
  628.  
  629.  
  630.  
  631. static void
  632. render_image_rgb_a (RenderInfo *info)
  633. {
  634.   guchar *src;
  635.   guchar *dest;
  636.   guint *alpha;
  637.   gulong r, g, b;
  638.   guint a;
  639.   int dark_light;
  640.   int byte_order;
  641.   int y, ye;
  642.   int x, xe;
  643.   int initial;
  644.   float error;
  645.   float step;
  646.  
  647.   alpha = info->alpha;
  648.  
  649.   y = info->y;
  650.   ye = info->y + info->h;
  651.   xe = info->x + info->w;
  652.  
  653.   step = 1.0 / info->scaley;
  654.  
  655.   error = y * step;
  656.   error -= ((int)error) - step;
  657.  
  658.   initial = TRUE;
  659.   byte_order = info->byte_order;
  660.   info->src = render_image_tile_fault (info);
  661.  
  662.   for (; y < ye; y++)
  663.     {
  664.       if (!initial && (error < 1.0) && (y & check_mod))
  665.     memcpy (info->dest, info->dest - info->dest_bpl, info->dest_width);
  666.       else
  667.     {
  668.       src = info->src;
  669.       dest = info->dest;
  670.  
  671.       dark_light = (y >> check_shift) + (info->x >> check_shift);
  672.  
  673.       g_return_if_fail (src != NULL);
  674.  
  675.       for (x = info->x; x < xe; x++)
  676.         {
  677.           a = alpha[src[ALPHA_PIX]];
  678.           if (dark_light & 0x1)
  679.         {
  680.           r = blend_dark_check[(a | src[RED_PIX])];
  681.           g = blend_dark_check[(a | src[GREEN_PIX])];
  682.           b = blend_dark_check[(a | src[BLUE_PIX])];
  683.         }
  684.           else
  685.         {
  686.           r = blend_light_check[(a | src[RED_PIX])];
  687.           g = blend_light_check[(a | src[GREEN_PIX])];
  688.           b = blend_light_check[(a | src[BLUE_PIX])];
  689.         }
  690.  
  691.           src += 4;
  692.  
  693.           dest[0] = r;
  694.           dest[1] = g;
  695.           dest[2] = b;
  696.           dest += 3;
  697.  
  698.           if (((x + 1) & check_mod) == 0)
  699.         dark_light += 1;
  700.         }
  701.     }
  702.  
  703.       info->dest += info->dest_bpl;
  704.  
  705.       initial = FALSE;
  706.  
  707.       if (error >= 1.0)
  708.     {
  709.       info->src_y += (int)error;
  710.       error -= (int)error;
  711.       info->src = render_image_tile_fault (info);
  712.       initial = TRUE;
  713.     }
  714.  
  715.       error += step;
  716.     }
  717. }
  718.  
  719. static void
  720. render_image_init_info (RenderInfo *info,
  721.             GDisplay   *gdisp,
  722.             int         x,
  723.             int         y,
  724.             int         w,
  725.             int         h)
  726. {
  727.   info->gdisp = gdisp;
  728.   info->src_tiles = gimage_projection (gdisp->gimage);
  729.   info->x = x + gdisp->offset_x;
  730.   info->y = y + gdisp->offset_y;
  731.   info->w = w;
  732.   info->h = h;
  733.   info->scalex = SCALEFACTOR_X (gdisp);
  734.   info->scaley = SCALEFACTOR_Y (gdisp);
  735.   info->src_x = UNSCALEX (gdisp, info->x);
  736.   info->src_y = UNSCALEY (gdisp, info->y);
  737.   info->src_bpp = gimage_projection_bytes (gdisp->gimage);
  738.   info->dest = gximage_get_data ();
  739.   info->dest_bpp = gximage_get_bpp ();
  740.   info->dest_bpl = gximage_get_bpl ();
  741.   info->dest_width = info->w * info->dest_bpp;
  742.   info->byte_order = gximage_get_byte_order ();
  743.   info->scale = render_image_accelerate_scaling (w, info->x, info->scalex);
  744.   info->alpha = NULL;
  745.  
  746.   switch (gimage_projection_type (gdisp->gimage))
  747.     {
  748.     case RGBA_GIMAGE:
  749.     case GRAYA_GIMAGE:
  750.     case INDEXEDA_GIMAGE:
  751.       info->alpha = render_image_init_alpha (gimage_projection_opacity (gdisp->gimage));
  752.       break;
  753.     default:
  754.       /* nothing special needs doing */
  755.       break;
  756.     }
  757. }
  758.  
  759. static guint*
  760. render_image_init_alpha (int mult)
  761. {
  762.   static guint *alpha_mult = NULL;
  763.   static int alpha_val = -1;
  764.   int i;
  765.  
  766.   if (alpha_val != mult)
  767.     {
  768.       if (!alpha_mult)
  769.     alpha_mult = g_new (guint, 256);
  770.  
  771.       alpha_val = mult;
  772.       for (i = 0; i < 256; i++)
  773.     alpha_mult[i] = ((mult * i) / 255) << 8;
  774.     }
  775.  
  776.   return alpha_mult;
  777. }
  778.  
  779. static guchar*
  780. render_image_accelerate_scaling (int   width,
  781.                  int   start,
  782.                  float scalex)
  783. {
  784.   static guchar *scale = NULL;
  785.   float error;
  786.   float step;
  787.   int i;
  788.  
  789.   if (!scale)
  790.     scale = g_new (guchar, GXIMAGE_WIDTH + 1);
  791.  
  792.   step = 1.0 / scalex;
  793.  
  794.   error = start * step;
  795.   error -= ((int)error) - step;
  796.  
  797.   for (i = 0; i <= width; i++)
  798.   {
  799.     scale[i] = ((int)error);
  800.     error += step - (int)error;
  801.   }    
  802.  
  803.   return scale;
  804. }
  805.  
  806. static guchar*
  807. render_image_tile_fault (RenderInfo *info)
  808. {
  809.   Tile *tile;
  810.   guchar *data;
  811.   guchar *dest;
  812.   guchar *scale;
  813.   int width;
  814.   int tilex;
  815.   int tiley;
  816.   int srctilex, srctiley;
  817.   int step;
  818.   int bpp = info->src_bpp;
  819.   int x, b;
  820.  
  821.   tilex = info->src_x / TILE_WIDTH;
  822.   tiley = info->src_y / TILE_HEIGHT;
  823.  
  824.   tile = tile_manager_get_tile (info->src_tiles,
  825.                 srctilex=info->src_x, srctiley=info->src_y,
  826.                 TRUE, FALSE);
  827.   if (!tile)
  828.     return NULL;
  829.  
  830.   data = tile_data_pointer (tile, 
  831.                 info->src_x % TILE_WIDTH,
  832.                 info->src_y % TILE_HEIGHT);
  833.   scale = info->scale;
  834.   dest = tile_buf;
  835.  
  836.   x = info->src_x;
  837.   width = info->w;
  838.  
  839.   while (width--)
  840.     {
  841.       for (b = 0; b < bpp; b++)
  842.     *dest++ = data[b];
  843.  
  844.       step = *scale++;
  845.       if (step != 0)
  846.     {
  847.       x += step;
  848.       data += step * bpp;
  849.  
  850.       if ((x >> tile_shift) != tilex)
  851.         {
  852.           tile_release (tile, FALSE);
  853.           tilex += 1;
  854.  
  855.           tile = tile_manager_get_tile (info->src_tiles, srctilex=x,
  856.                         srctiley=info->src_y, TRUE, FALSE);
  857.           if (!tile)
  858.         return tile_buf;
  859.  
  860.           data = tile_data_pointer (tile, 
  861.                 x % TILE_WIDTH,
  862.                 info->src_y % TILE_HEIGHT);
  863.         }
  864.     }
  865.     }
  866.  
  867.   tile_release (tile, FALSE);
  868.   return tile_buf;
  869. }
  870.