Files
core/DesktopEditor/cximage/libpsd/gradient_blend.c
Elen.Subbotina e89cf2f58f .....
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@61945 954022d7-b5bf-4e40-9824-e11837661b57
2016-05-20 23:54:34 +03:00

891 lines
26 KiB
C

/**
* libpsd - Photoshop file formats (*.psd) decode library
* Copyright (C) 2004-2007 Graphest Software.
*
* libpsd is the legal property of its developers, whose names are too numerous
* to list here. Please refer to the COPYRIGHT file distributed with this
* source distribution.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: gradient_blend.c, created by Patrick in 2006.06.22, libpsd@graphest.com Exp $
*/
#include "libpsd.h"
#include "psd_system.h"
#include "psd_color.h"
#include "psd_fixed.h"
#include "psd_bitmap.h"
#include "psd_gradient.h"
#include "psd_math.h"
#define PSD_COLOR_SCALE 4
// from quake3 source code
psd_float psd_carm_sqrt(psd_float x)
{
union
{
psd_int intPart;
psd_float floatPart;
} convertor;
union
{
psd_int intPart;
psd_float floatPart;
} convertor2;
convertor.floatPart = x;
convertor2.floatPart = x;
convertor.intPart = 0x1FBCF800 + (convertor.intPart >> 1);
convertor2.intPart = 0x5f3759df - (convertor2.intPart >> 1);
return 0.5f*(convertor.floatPart + (x * convertor2.floatPart));
}
void psd_gradient_color_get_table(psd_gradient_color * gradient_color, psd_argb_color * color_table, psd_int table_count, psd_bool reverse)
{
psd_int i, j;
psd_argb_color color;
psd_int r1, r2, r3, g1, g2, g3, b1, b2, b3;
psd_fixed_16_16 red, green, blue, red_step, green_step, blue_step;
psd_int midpoint, location1, location2;
psd_int o1, o2, o3;
psd_uint high_opacity;
psd_fixed_16_16 opacity, opacity_step;
if(gradient_color == NULL)
return;
if(gradient_color->color_stop[0].location > 0)
{
location1 = 0;
location2 = (gradient_color->color_stop[0].location * table_count + 2048) / 4096;
psd_color_memset(color_table + location1, gradient_color->color_stop[0].actual_color,
location2 - location1);
}
for(i = 0; i < gradient_color->number_color_stops - 1; i ++)
{
location1 = (gradient_color->color_stop[i].location * table_count + 2048) / 4096;
location2 = (gradient_color->color_stop[i + 1].location * table_count + 2048) / 4096;
if(gradient_color->color_stop[i].actual_color == gradient_color->color_stop[i + 1].actual_color)
{
psd_color_memset(color_table + location1, gradient_color->color_stop[i].actual_color,
location2 - location1);
continue;
}
color = gradient_color->color_stop[i].actual_color;
r1 = psd_get_red_component(color);
g1 = psd_get_green_component(color);
b1 = psd_get_blue_component(color);
color = gradient_color->color_stop[i + 1].actual_color;
r3 = psd_get_red_component(color);
g3 = psd_get_green_component(color);
b3 = psd_get_blue_component(color);
if(gradient_color->color_stop[i + 1].midpoint == 50)
{
red = PSD_FIXED_16_16_INT(r1);
green = PSD_FIXED_16_16_INT(g1);
blue = PSD_FIXED_16_16_INT(b1);
red_step = PSD_FIXED_16_16_INT(r3 - r1) / (location2 - location1);
green_step = PSD_FIXED_16_16_INT(g3 - g1) / (location2 - location1);
blue_step = PSD_FIXED_16_16_INT(b3 - b1) / (location2 - location1);
for(j = location1; j < location2; j ++)
{
color_table[j] = PSD_RGB_TO_COLOR(PSD_FIXED_16_16_ROUND(red),
PSD_FIXED_16_16_ROUND(green), PSD_FIXED_16_16_ROUND(blue));
red += red_step;
green += green_step;
blue += blue_step;
}
}
else
{
midpoint = location1 + (gradient_color->color_stop[i + 1].midpoint *
(location2 - location1) + 50) / 100;
r2 = (r1 + r3) / 2;
g2 = (g1 + g3) / 2;
b2 = (b1 + b3) / 2;
red = PSD_FIXED_16_16_INT(r1);
green = PSD_FIXED_16_16_INT(g1);
blue = PSD_FIXED_16_16_INT(b1);
red_step = PSD_FIXED_16_16_INT(r2 - r1) / (midpoint - location1);
green_step = PSD_FIXED_16_16_INT(g2 - g1) / (midpoint - location1);
blue_step = PSD_FIXED_16_16_INT(b2 - b1) / (midpoint - location1);
for(j = location1; j < midpoint; j ++)
{
color_table[j] = PSD_RGB_TO_COLOR(PSD_FIXED_16_16_ROUND(red),
PSD_FIXED_16_16_ROUND(green), PSD_FIXED_16_16_ROUND(blue));
red += red_step;
green += green_step;
blue += blue_step;
}
red = PSD_FIXED_16_16_INT(r2);
green = PSD_FIXED_16_16_INT(g2);
blue = PSD_FIXED_16_16_INT(b2);
red_step = PSD_FIXED_16_16_INT(r3 - r2) / (location2 - midpoint);
green_step = PSD_FIXED_16_16_INT(g3 - g2) / (location2 - midpoint);
blue_step = PSD_FIXED_16_16_INT(b3 - b2) / (location2 - midpoint);
for(j = midpoint; j < location2; j ++)
{
color_table[j] = PSD_RGB_TO_COLOR(PSD_FIXED_16_16_ROUND(red),
PSD_FIXED_16_16_ROUND(green), PSD_FIXED_16_16_ROUND(blue));
red += red_step;
green += green_step;
blue += blue_step;
}
}
}
if(gradient_color->color_stop[gradient_color->number_color_stops - 1].location < 4096)
{
location1 = (gradient_color->color_stop[gradient_color->number_color_stops - 1].location * table_count + 2048) / 4096;
location2 = table_count;
psd_color_memset(color_table + location1, gradient_color->color_stop[gradient_color->number_color_stops - 1].actual_color,
location2 - location1);
}
if(gradient_color->transparency_stop[0].location > 0)
{
if(gradient_color->transparency_stop[0].opacity != 100)
{
location1 = 0;
location2 = (gradient_color->transparency_stop[0].location * table_count + 2048) / 4096;
high_opacity = (gradient_color->transparency_stop[0].opacity * 255 + 50) / 100;
high_opacity <<= 24;
for(j = location1; j < location2; j ++)
{
color_table[j] = (color_table[j] & 0x00FFFFFF) | high_opacity;
}
}
}
for(i = 0; i < gradient_color->number_transparency_stops - 1; i ++)
{
if(gradient_color->transparency_stop[i].opacity == 100 &&
gradient_color->transparency_stop[i + 1].opacity == 100)
{
continue;
}
location1 = (gradient_color->transparency_stop[i].location * table_count + 2048) / 4096;
location2 = (gradient_color->transparency_stop[i + 1].location * table_count + 2048) / 4096;
if(gradient_color->transparency_stop[i].opacity ==
gradient_color->transparency_stop[i + 1].opacity)
{
high_opacity = (gradient_color->transparency_stop[i].opacity * 255 + 50) / 100;
high_opacity <<= 24;
for(j = location1; j < location2; j ++)
{
color_table[j] = (color_table[j] & 0x00FFFFFF) | high_opacity;
}
}
else
{
o1 = (gradient_color->transparency_stop[i].opacity * 255 + 50) / 100;
o3 = (gradient_color->transparency_stop[i + 1].opacity * 255 + 50) / 100;
if(gradient_color->transparency_stop[i + 1].midpoint == 50)
{
opacity = PSD_FIXED_16_16_INT(o1);
opacity_step = PSD_FIXED_16_16_INT(o3 - o1) / (location2 - location1);
for(j = location1; j < location2 ; j ++)
{
color_table[j] = (color_table[j] & 0x00FFFFFF) |
(PSD_FIXED_16_16_ROUND(opacity) << 24);
opacity += opacity_step;
}
}
else
{
o2 = (o1 + o3) / 2;
midpoint = location1 + (gradient_color->transparency_stop[i + 1].midpoint *
(location2 - location1) + 50) / 100;
opacity = PSD_FIXED_16_16_INT(o1);
opacity_step = PSD_FIXED_16_16_INT(o2 - o1) / (midpoint - location1);
for(j = location1; j < midpoint; j ++)
{
color_table[j] = (color_table[j] & 0x00FFFFFF) |
(PSD_FIXED_16_16_ROUND(opacity) << 24);
opacity += opacity_step;
}
opacity = PSD_FIXED_16_16_INT(o2);
opacity_step = PSD_FIXED_16_16_INT(o3 - o2) / (location2 - midpoint);
for(j = midpoint; j < location2; j ++)
{
color_table[j] = (color_table[j] & 0x00FFFFFF) |
(PSD_FIXED_16_16_ROUND(opacity) << 24);
opacity += opacity_step;
}
}
}
}
if(gradient_color->transparency_stop[gradient_color->number_transparency_stops - 1].location < 4096)
{
if(gradient_color->transparency_stop[gradient_color->number_transparency_stops - 1].opacity != 100)
{
location1 = (gradient_color->transparency_stop[gradient_color->number_transparency_stops - 1].location * table_count + 2048) / 4096;
location2 = table_count;
high_opacity = (gradient_color->transparency_stop[gradient_color->number_transparency_stops - 1].opacity * 255 + 50) / 100;
high_opacity <<= 24;
for(j = location1; j < location2; j ++)
{
color_table[j] = (color_table[j] & 0x00FFFFFF) | high_opacity;
}
}
}
if(reverse == psd_true)
{
j = table_count / 2;
for(i = 0; i < j; i ++)
{
color = color_table[i];
color_table[i] = color_table[table_count - 1 - i];
color_table[table_count - 1 - i] = color;
}
}
}
psd_status psd_gradient_fill_linear(psd_bitmap * bitmap, psd_gradient_color * gradient_color, psd_bool reverse,
psd_int start_x, psd_int start_y, psd_int end_x, psd_int end_y)
{
psd_int distance, table_count;
psd_argb_color * color_table;
psd_int temp, i, j, width, height, index;
psd_argb_color * dst_data, cur_color;
psd_fixed_16_16 delta_x, delta_y, line_x, pixel_x;
width = bitmap->width;
height = bitmap->height;
if(start_x == end_x)
{
table_count = PSD_ABS(end_y - start_y);
color_table = (psd_argb_color *)psd_malloc(table_count * 4);
if(color_table == NULL)
return psd_status_malloc_failed;
if(start_y > end_y)
{
temp = start_y;
start_y = end_y;
end_y = temp;
reverse = psd_true - reverse;
}
psd_gradient_color_get_table(gradient_color, color_table, table_count, reverse);
dst_data = bitmap->image_data;
cur_color = color_table[0];
for(i = 0; i < PSD_MIN(start_y, height); i ++)
{
psd_color_memset(dst_data, cur_color, width);
dst_data += width;
}
for(i = PSD_MAX(start_y, 0); i < PSD_MIN(end_y, height); i ++)
{
cur_color = color_table[i - start_y];
psd_color_memset(dst_data, cur_color, width);
dst_data += width;
}
cur_color = color_table[table_count - 1];
for(i = PSD_MAX(end_y, 0); i < height; i ++)
{
psd_color_memset(dst_data, cur_color, width);
dst_data += width;
}
}
else if(start_y == end_y)
{
table_count = PSD_ABS(end_x - start_x);
color_table = (psd_argb_color *)psd_malloc(table_count * 4);
if(color_table == NULL)
return psd_status_malloc_failed;
if(start_x > end_x)
{
temp = start_x;
start_x = end_x;
end_x = temp;
reverse = psd_true - reverse;
}
psd_gradient_color_get_table(gradient_color, color_table, table_count, reverse);
dst_data = bitmap->image_data;
cur_color = color_table[0];
for(i = 0; i < PSD_MIN(start_x, width); i ++)
{
*dst_data = cur_color;
dst_data ++;
}
for(i = PSD_MAX(start_x, 0); i < PSD_MIN(end_x, width); i ++)
{
cur_color = color_table[i - start_x];
*dst_data = cur_color;
dst_data ++;
}
cur_color = color_table[table_count - 1];
for(i = PSD_MAX(end_x, 0); i < width; i ++)
{
*dst_data = cur_color;
dst_data ++;
}
for(i = 1; i < height; i ++)
{
memcpy(dst_data, bitmap->image_data, width * 4);
dst_data += width;
}
}
else
{
distance = (psd_int)psd_carm_sqrt((psd_float)((end_x - start_x) * (end_x - start_x) + (end_y - start_y) * (end_y - start_y)) + 0.5f);
table_count = distance * PSD_COLOR_SCALE;
color_table = (psd_argb_color *)psd_malloc(table_count * 4);
if(color_table == NULL)
return psd_status_malloc_failed;
psd_gradient_color_get_table(gradient_color, color_table, table_count, reverse);
delta_x = PSD_FIXED_16_16_INT(end_x - start_x) / distance;
delta_y = PSD_FIXED_16_16_INT(end_y - start_y) / distance;
line_x = -delta_y * start_y - delta_x * start_x;
line_x *= PSD_COLOR_SCALE;
delta_x *= PSD_COLOR_SCALE;
delta_y *= PSD_COLOR_SCALE;
dst_data = bitmap->image_data;
for(i = 0; i < height; i ++)
{
pixel_x = line_x;
for(j = 0; j < width; j ++)
{
index = PSD_FIXED_16_16_ROUND(pixel_x);
if(index <= 0)
cur_color = color_table[0];
else if(index >= table_count - 1)
cur_color = color_table[table_count - 1];
else
cur_color = color_table[index];
*dst_data = cur_color;
dst_data ++;
pixel_x += delta_x;
}
line_x += delta_y;
}
}
psd_free(color_table);
return psd_status_done;
}
psd_status psd_gradient_fill_radial(psd_bitmap * bitmap, psd_gradient_color * gradient_color, psd_bool reverse,
psd_int center_x, psd_int center_y, psd_int radius)
{
psd_int width, height, left, top, right, bottom, i, j, ii, i2, j2;
psd_int table_count, distance;
psd_argb_color * color_table;
psd_argb_color * dst_data, cur_color;
width = bitmap->width;
height = bitmap->height;
left = center_x > radius ? center_x - radius : 0;
top = center_y > radius ? center_y - radius : 0;
right = center_x + radius < width ? center_x + radius : width;
bottom = center_y + radius < height ? center_y + radius : height;
if(center_x < width / 2)
left = center_x - (right - center_x);
else
right = center_x + (center_x - left);
if(center_y < height / 2)
top = center_y - (bottom - center_y);
else
bottom = center_y + (center_y - top);
table_count = radius * PSD_COLOR_SCALE;
color_table = (psd_argb_color *)psd_malloc(table_count * 4);
if(color_table == NULL)
return psd_status_malloc_failed;
psd_gradient_color_get_table(gradient_color, color_table, table_count, reverse);
cur_color = color_table[table_count - 1];
if(top >= 0)
{
dst_data = bitmap->image_data;
for(i = 0; i <= PSD_MIN(top, height - 1); i ++)
{
psd_color_memset(dst_data, cur_color, width);
dst_data += width;
}
}
if(bottom < height)
{
dst_data = bitmap->image_data + PSD_MAX(bottom, 0) * width;
for(i = PSD_MAX(bottom, 0); i < height; i ++)
{
psd_color_memset(dst_data, cur_color, width);
dst_data += width;
}
}
if(left >= 0)
{
dst_data = bitmap->image_data + PSD_MAX(top, 0) * width;
for(i = PSD_MAX(top, 0); i < PSD_MIN(bottom, height); i ++)
{
psd_color_memset(dst_data, cur_color, PSD_MIN(left + 1, width));
dst_data += width;
}
}
if(right < width)
{
dst_data = bitmap->image_data + PSD_MAX(top, 0) * width + PSD_MAX(right, 0);
for(i = PSD_MAX(top, 0); i < PSD_MIN(bottom, height); i ++)
{
psd_color_memset(dst_data, cur_color, PSD_MIN(width - right, width));
dst_data += width;
}
}
if(center_x >= 0 && center_x < width)
{
dst_data = bitmap->image_data + PSD_MAX(top + 1, 0) * width + center_x;
for(i = PSD_MAX(top + 1, 0); i < PSD_MIN(bottom - 1, height); i ++)
{
distance = PSD_ABS(i - center_y) * PSD_COLOR_SCALE;
cur_color = color_table[distance];
*dst_data = cur_color;
dst_data += width;
}
}
if(center_y >= 0 && center_y < height)
{
dst_data = bitmap->image_data + center_y * width + PSD_MAX(left + 1, 0);
for(i = PSD_MAX(left + 1, 0); i < PSD_MIN(right - 1, width); i ++)
{
distance = PSD_ABS(i - center_x) * PSD_COLOR_SCALE;
cur_color = color_table[distance];
*dst_data = cur_color;
dst_data ++;
}
}
for(i = top + 1; i < center_y; i ++)
{
ii = (center_y - i) * (center_y - i);
i2 = center_y + (center_y - i);
dst_data = bitmap->image_data + i * width + (left + 1);
for(j = left + 1; j < center_x; j ++, dst_data ++)
{
distance = (psd_int)(psd_carm_sqrt((psd_float)(ii + (center_x - j) * (center_x - j))) * PSD_COLOR_SCALE + 0.5);
if(distance >= table_count)
cur_color = color_table[table_count - 1];
else
cur_color = color_table[distance];
j2 = center_x + (center_x - j);
if(i >= 0 && i < height)
{
if(j >= 0 && j < width)
*dst_data = cur_color;
if(j2 >= 0 && j2 < width)
*(dst_data + (j2 - j)) = cur_color;
}
if(i2 >= 0 && i2 < height)
{
if(j >= 0 && j < width)
*(dst_data + (i2 - i) * width) = cur_color;
if(j2 >= 0 && j2 < width)
*(dst_data + (i2 - i) * width + (j2 - j)) = cur_color;
}
}
}
psd_free(color_table);
return psd_status_done;
}
psd_status psd_gradient_fill_angle(psd_bitmap * bitmap, psd_gradient_color * gradient_color, psd_bool reverse,
psd_int center_x, psd_int center_y, psd_int angle)
{
psd_int left, top, width, height, i, j, i2, j2, dx, dy, tan_angle, cur_angle;
psd_argb_color * color_table;
psd_argb_color * dst_data, cur_color;
width = bitmap->width;
height = bitmap->height;
left = center_x < width / 2 ? center_x - (width - center_x) : 0;
top = center_y < height / 2 ? center_y - (height - center_y) : 0;
color_table = (psd_argb_color *)psd_malloc(360 * 4);
if(color_table == NULL)
return psd_status_malloc_failed;
psd_gradient_color_get_table(gradient_color, color_table, 360, (unsigned char)(psd_true - reverse));
if(center_x >= 0 && center_x < width)
{
if(center_y > 0)
{
cur_angle = (90 - angle + 360) % 360;
cur_color = color_table[cur_angle];
dst_data = bitmap->image_data + center_x;
for(i = 0; i < PSD_MIN(center_y, height); i ++)
{
*dst_data = cur_color;
dst_data += width;
}
}
if(center_y + 1 < height)
{
cur_angle = (270 - angle + 360) % 360;
cur_color = color_table[cur_angle];
dst_data = bitmap->image_data + PSD_MAX(center_y + 1, 0) * width + center_x;
for(i = PSD_MAX(center_y + 1, 0); i < height; i ++)
{
*dst_data = cur_color;
dst_data += width;
}
}
}
if(center_y >= 0 && center_y < height)
{
if(center_x > 0)
{
cur_angle = (180 - angle + 360) % 360;
cur_color = color_table[cur_angle];
dst_data = bitmap->image_data + center_y * width;
psd_color_memset(dst_data, cur_color, PSD_MIN(center_x, width));
}
if(center_x + 1 < width)
{
cur_angle = (-angle + 360) % 360;
cur_color = color_table[cur_angle];
dst_data = bitmap->image_data + center_y * width + PSD_MAX(center_x + 1, 0);
psd_color_memset(dst_data, cur_color, width - PSD_MAX(center_x + 1, 0));
}
}
if(center_x >= 0 && center_x < width && center_y >= 0 && center_y < height)
{
dst_data = bitmap->image_data + center_y * width + center_x;
*dst_data = color_table[0];
}
for(i = top; i < center_y; i ++)
{
i2 = center_y + (center_y - i);
dy = center_y - i;
dst_data = bitmap->image_data + i * width + left;
for(j = left; j < center_x; j ++, dst_data ++)
{
j2 = center_x + (center_x - j);
dx = center_x - j;
if(dx >= dy)
tan_angle = (dy * 45 + (dx >> 1)) / dx;
else
tan_angle = 90 - (dx * 45 + (dy >> 1)) / dy;
tan_angle = PSD_CONSTRAIN(tan_angle, 1, 89);
cur_angle = 90 - tan_angle - angle + 90;
if(cur_angle < 0)
cur_angle += 360;
else if(cur_angle >= 360)
cur_angle -= 360;
if(j >= 0 && j < width)
{
if(i >= 0 && i < height)
*dst_data = color_table[cur_angle];
if(i2 >= 0 && i2 < height)
{
cur_angle += tan_angle * 2;
if(cur_angle >= 360)
cur_angle -= 360;
*(dst_data + (i2 - i) * width) = color_table[cur_angle];
cur_angle += 180 - tan_angle * 2;
if(cur_angle >= 360)
cur_angle -= 360;
}
else
{
cur_angle += 180;
if(cur_angle >= 360)
cur_angle -= 360;
}
}
else
{
cur_angle += 180;
if(cur_angle >= 360)
cur_angle -= 360;
}
if(j2 >= 0 && j2 < width)
{
if(i2 >= 0 && i2 < height)
*(dst_data + (i2 - i) * width + (j2 - j)) = color_table[cur_angle];
if(i >= 0 && i < height)
{
cur_angle += tan_angle * 2;
if(cur_angle >= 360)
cur_angle -= 360;
*(dst_data + (j2 - j)) = color_table[cur_angle];
}
}
}
}
psd_free(color_table);
return psd_status_done;
}
psd_status psd_gradient_fill_reflected(psd_bitmap * bitmap, psd_gradient_color * gradient_color, psd_bool reverse,
psd_int start_x, psd_int start_y, psd_int end_x, psd_int end_y)
{
psd_int distance, table_count;
psd_argb_color * color_table;
psd_int temp, i, j, width, height, index;
psd_argb_color * dst_data, cur_color;
psd_fixed_16_16 delta_x, delta_y, line_x, pixel_x;
width = bitmap->width;
height = bitmap->height;
if(start_x == end_x)
{
table_count = PSD_ABS(end_y - start_y);
color_table = (psd_argb_color *)psd_malloc(table_count * 4);
if(color_table == NULL)
return psd_status_malloc_failed;
if(start_y > end_y)
{
temp = start_y;
start_y = end_y;
end_y = temp;
}
psd_gradient_color_get_table(gradient_color, color_table, table_count / 2, (unsigned char)(psd_true - reverse));
psd_gradient_color_get_table(gradient_color, color_table + table_count / 2, table_count - table_count / 2, reverse);
dst_data = bitmap->image_data;
cur_color = color_table[0];
for(i = 0; i < PSD_MIN(start_y, height); i ++)
{
psd_color_memset(dst_data, cur_color, width);
dst_data += width;
}
for(i = PSD_MAX(start_y, 0); i < PSD_MIN(end_y, height); i ++)
{
cur_color = color_table[i - start_y];
psd_color_memset(dst_data, cur_color, width);
dst_data += width;
}
cur_color = color_table[table_count - 1];
for(i = PSD_MAX(end_y, 0); i < height; i ++)
{
psd_color_memset(dst_data, cur_color, width);
dst_data += width;
}
}
else if(start_y == end_y)
{
table_count = PSD_ABS(end_x - start_x);
color_table = (psd_argb_color *)psd_malloc(table_count * 4);
if(color_table == NULL)
return psd_status_malloc_failed;
if(start_x > end_x)
{
temp = start_x;
start_x = end_x;
end_x = temp;
}
psd_gradient_color_get_table(gradient_color, color_table, table_count / 2, (unsigned char)(psd_true - reverse));
psd_gradient_color_get_table(gradient_color, color_table + table_count / 2, table_count - table_count / 2, reverse);
dst_data = bitmap->image_data;
cur_color = color_table[0];
for(i = 0; i < PSD_MIN(start_x, width); i ++)
{
*dst_data = cur_color;
dst_data ++;
}
for(i = PSD_MAX(start_x, 0); i < PSD_MIN(end_x, width); i ++)
{
cur_color = color_table[i - start_x];
*dst_data = cur_color;
dst_data ++;
}
cur_color = color_table[table_count - 1];
for(i = PSD_MAX(end_x, 0); i < width; i ++)
{
*dst_data = cur_color;
dst_data ++;
}
for(i = 1; i < height; i ++)
{
memcpy(dst_data, bitmap->image_data, width * 4);
dst_data += width;
}
}
else
{
distance = (psd_int)psd_carm_sqrt((psd_float)((end_x - start_x) * (end_x - start_x) + (end_y - start_y) * (end_y - start_y)) + 0.5f);
table_count = distance * PSD_COLOR_SCALE;
color_table = (psd_argb_color *)psd_malloc(table_count * 4);
if(color_table == NULL)
return psd_status_malloc_failed;
psd_gradient_color_get_table(gradient_color, color_table, table_count / 2, (unsigned char)(psd_true - reverse));
psd_gradient_color_get_table(gradient_color, color_table + table_count / 2, table_count - table_count / 2, reverse);
delta_x = PSD_FIXED_16_16_INT(end_x - start_x) / distance;
delta_y = PSD_FIXED_16_16_INT(end_y - start_y) / distance;
line_x = -delta_y * start_y - delta_x * start_x;
line_x *= PSD_COLOR_SCALE;
delta_x *= PSD_COLOR_SCALE;
delta_y *= PSD_COLOR_SCALE;
dst_data = bitmap->image_data;
for(i = 0; i < height; i ++)
{
pixel_x = line_x;
for(j = 0; j < width; j ++)
{
index = PSD_FIXED_16_16_ROUND(pixel_x);
if(index <= 0)
cur_color = color_table[0];
else if(index >= table_count - 1)
cur_color = color_table[table_count - 1];
else
cur_color = color_table[index];
*dst_data = cur_color;
dst_data ++;
pixel_x += delta_x;
}
line_x += delta_y;
}
}
psd_free(color_table);
return psd_status_done;
}
psd_status psd_gradient_fill_diamond(psd_bitmap * bitmap, psd_gradient_color * gradient_color, psd_bool reverse,
psd_int center_x, psd_int center_y, psd_int radius, psd_int angle)
{
psd_int width, height, i, j, dx, dy;
psd_float ax, ay, xy;
psd_int distance, table_count;
psd_argb_color * color_table;
psd_argb_color * dst_data, cur_color;
psd_fixed_16_16 angle_sin, angle_cos;
angle = (angle + 360) % 90;
width = bitmap->width;
height = bitmap->height;
if(angle == 0)
{
table_count = radius;
color_table = (psd_argb_color *)psd_malloc(table_count * 4);
if(color_table == NULL)
return psd_status_malloc_failed;
psd_gradient_color_get_table(gradient_color, color_table, table_count, reverse);
dst_data = bitmap->image_data;
for(i = 0; i < height; i ++)
{
for(j = 0; j < width; j ++, dst_data ++)
{
distance = PSD_ABS(j - center_x) + PSD_ABS(i - center_y);
if(distance >= table_count)
cur_color = color_table[table_count - 1];
else
cur_color = color_table[distance];
*dst_data = cur_color;
}
}
}
else
{
table_count = radius * PSD_COLOR_SCALE;
color_table = (psd_argb_color *)psd_malloc(table_count * 4);
if(color_table == NULL)
return psd_status_malloc_failed;
psd_gradient_color_get_table(gradient_color, color_table, table_count, reverse);
if(angle <= 45)
{
ax = 1;
ay = angle / 45.0f;
}
else
{
ay = 1;
ax = (90 - angle) / 45.0f;
}
xy = psd_carm_sqrt(ax * ax + ay * ay);
angle_sin = psd_fixed_16_16_float(ax / xy);
angle_cos = psd_fixed_16_16_float(ay / xy);
dst_data = bitmap->image_data;
for(i = 0; i < height; i ++)
{
for(j = 0; j < width; j ++, dst_data ++)
{
dx = (j - center_x) * angle_cos + (i - center_y) * angle_sin;
dy = -(j - center_x) * angle_sin + (i - center_y) * angle_cos;
distance = PSD_FIXED_16_16_ROUND((PSD_ABS(dx) + PSD_ABS(dy)) * PSD_COLOR_SCALE);
if(distance >= table_count)
cur_color = color_table[table_count - 1];
else
cur_color = color_table[distance];
*dst_data = cur_color;
}
}
}
psd_free(color_table);
return psd_status_done;
}