mirror of
https://github.com/ONLYOFFICE/core.git
synced 2026-02-10 18:05:41 +08:00
git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@61945 954022d7-b5bf-4e40-9824-e11837661b57
891 lines
26 KiB
C
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;
|
|
}
|
|
|