1 Star 1 Fork 2

weimingtom/Onscripter-Official

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
AnimationInfo.cpp 37.90 KB
一键复制 编辑 原始数据 按行查看 历史
只要998 提交于 2020-04-21 07:03 . 20200306
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196
/* -*- C++ -*-
*
* AnimationInfo.cpp - General image storage class of ONScripter
*
* Copyright (c) 2001-2020 Ogapee. All rights reserved.
*
* ogapee@aqua.dti2.ne.jp
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU 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 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
*/
#include "AnimationInfo.h"
#include <math.h>
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
AnimationInfo::AnimationInfo()
{
image_name = NULL;
surface_name = NULL;
mask_surface_name = NULL;
image_surface = NULL;
alpha_buf = NULL;
mutex = SDL_CreateMutex();
duration_list = NULL;
color_list = NULL;
file_name = NULL;
mask_file_name = NULL;
trans_mode = TRANS_TOPLEFT;
affine_flag = false;
reset();
}
AnimationInfo::AnimationInfo(const AnimationInfo &anim)
{
*this = anim;
}
AnimationInfo::~AnimationInfo()
{
reset();
if (mutex) SDL_DestroyMutex(mutex);
}
AnimationInfo& AnimationInfo::operator =(const AnimationInfo &anim)
{
if (this != &anim){
memcpy(this, &anim, sizeof(AnimationInfo));
mutex = SDL_CreateMutex();
if (image_name){
image_name = new char[ strlen(anim.image_name) + 1 ];
strcpy( image_name, anim.image_name );
}
if (surface_name){
surface_name = new char[ strlen(anim.surface_name) + 1 ];
strcpy( surface_name, anim.surface_name );
}
if (mask_surface_name){
mask_surface_name = new char[ strlen(anim.mask_surface_name) + 1 ];
strcpy( mask_surface_name, anim.mask_surface_name );
}
if (file_name){
file_name = new char[ strlen(anim.file_name) + 1 ];
strcpy( file_name, anim.file_name );
}
if (mask_file_name){
mask_file_name = new char[ strlen(anim.mask_file_name) + 1 ];
strcpy( mask_file_name, anim.mask_file_name );
}
if (color_list){
color_list = new uchar3[ anim.num_of_cells ];
memcpy(color_list, anim.color_list, sizeof(uchar3)*anim.num_of_cells);
}
if (duration_list){
duration_list = new int[ anim.num_of_cells ];
memcpy(duration_list, anim.duration_list, sizeof(int)*anim.num_of_cells);
}
if (image_surface){
image_surface = allocSurface( anim.image_surface->w, anim.image_surface->h, texture_format );
memcpy(image_surface->pixels, anim.image_surface->pixels, anim.image_surface->pitch*anim.image_surface->h);
#if defined(BPP16)
alpha_buf = new unsigned char[image_surface->w*image_surface->h];
memcpy(alpha_buf, anim.alpha_buf, image_surface->w*image_surface->h);
#endif
}
}
return *this;
}
void AnimationInfo::reset()
{
remove();
trans = -1;
default_alpha = 0xff;
orig_pos.x = orig_pos.y = 0;
pos.x = pos.y = 0;
visible = false;
abs_flag = true;
scale_x = scale_y = rot = 0;
blending_mode = BLEND_NORMAL;
font_size_xy[0] = font_size_xy[1] = -1;
font_pitch[0] = font_pitch[1] = -1;
mat[0][0] = 1024;
mat[0][1] = 0;
mat[1][0] = 0;
mat[1][1] = 1024;
}
void AnimationInfo::deleteImageName(){
if ( image_name ) delete[] image_name;
image_name = NULL;
}
void AnimationInfo::setImageName( const char *name ){
deleteImageName();
image_name = new char[ strlen(name) + 1 ];
strcpy( image_name, name );
}
void AnimationInfo::deleteSurface(bool delete_surface_name)
{
if (delete_surface_name){
if ( surface_name ) delete[] surface_name;
surface_name = NULL;
if ( mask_surface_name ) delete[] mask_surface_name;
mask_surface_name = NULL;
}
SDL_mutexP(mutex);
if ( image_surface ) SDL_FreeSurface( image_surface );
image_surface = NULL;
SDL_mutexV(mutex);
if (alpha_buf) delete[] alpha_buf;
alpha_buf = NULL;
}
void AnimationInfo::remove()
{
deleteImageName();
deleteSurface();
removeTag();
}
void AnimationInfo::removeTag()
{
if ( duration_list ){
delete[] duration_list;
duration_list = NULL;
}
if ( color_list ){
delete[] color_list;
color_list = NULL;
}
if ( file_name ){
delete[] file_name;
file_name = NULL;
}
if ( mask_file_name ){
delete[] mask_file_name;
mask_file_name = NULL;
}
current_cell = 0;
num_of_cells = 0;
next_time = 0;
is_animatable = false;
is_single_line = true;
is_tight_region = true;
is_ruby_drawable = false;
is_2x = false;
is_flipped = false;
direction = 1;
color[0] = color[1] = color[2] = 0;
}
// 0 ... restart at the end
// 1 ... stop at the end
// 2 ... reverse at the end
// 3 ... no animation
bool AnimationInfo::proceedAnimation(int current_time)
{
if (!visible || !is_animatable || next_time > current_time) return false;
bool is_changed = false;
while(next_time <= current_time){
if ( loop_mode != 3 && num_of_cells > 0 ){
current_cell += direction;
is_changed = true;
}
if ( current_cell < 0 ){ // loop_mode must be 2
if (num_of_cells == 1)
current_cell = 0;
else
current_cell = 1;
direction = 1;
}
else if ( current_cell >= num_of_cells ){
if ( loop_mode == 0 ){
current_cell = 0;
}
else if ( loop_mode == 1 ){
current_cell = num_of_cells - 1;
is_changed = false;
}
else{
current_cell = num_of_cells - 2;
if (current_cell < 0)
current_cell = 0;
direction = -1;
}
}
next_time += duration_list[ current_cell ];
if (duration_list[ current_cell ] <= 0){
next_time = current_time;
break;
}
}
return is_changed;
}
void AnimationInfo::setCell(int cell)
{
if (cell < 0) cell = 0;
else if (cell >= num_of_cells) cell = num_of_cells - 1;
current_cell = cell;
}
int AnimationInfo::doClipping( SDL_Rect *dst, SDL_Rect *clip, SDL_Rect *clipped )
{
if ( clipped ) clipped->x = clipped->y = 0;
if ( !dst ||
dst->x >= clip->x + clip->w || dst->x + dst->w <= clip->x ||
dst->y >= clip->y + clip->h || dst->y + dst->h <= clip->y )
return -1;
if ( dst->x < clip->x ){
dst->w -= clip->x - dst->x;
if ( clipped ) clipped->x = clip->x - dst->x;
dst->x = clip->x;
}
if ( clip->x + clip->w < dst->x + dst->w ){
dst->w = clip->x + clip->w - dst->x;
}
if ( dst->y < clip->y ){
dst->h -= clip->y - dst->y;
if ( clipped ) clipped->y = clip->y - dst->y;
dst->y = clip->y;
}
if ( clip->y + clip->h < dst->y + dst->h ){
dst->h = clip->y + clip->h - dst->y;
}
if ( clipped ){
clipped->w = dst->w;
clipped->h = dst->h;
}
return 0;
}
// Dc = (1-Sa)Dc + SaSc
#if defined(BPP16)
#define BLEND_PIXEL()\
{\
if (*alphap == 255 && alpha == 256){\
*dst_buffer = *src_buffer;\
*lalphap = 0;\
}\
else if (*alphap != 0){\
Uint32 sa = (*alphap * alpha) >> 8;\
*lalphap = ((sa ^ 0xff) * (*lalphap + 1)) >> 8;\
sa = (sa + 1) >> 3;\
Uint32 s = (*src_buffer | *src_buffer << 16) & 0x07e0f81f;\
Uint32 d = (*dst_buffer | *dst_buffer << 16) & 0x07e0f81f;\
d = (d + ((s - d) * sa >> 5)) & 0x07e0f81f;\
*dst_buffer = d | d >> 16;\
}\
alphap++;\
}
#else
#define BLEND_PIXEL()\
{\
Uint32 sa = *src_buffer >> 24;\
if (sa == 255 && alpha == 256){\
*dst_buffer = *src_buffer;\
*lalphap = 0;\
}\
else if (sa != 0){\
sa = (sa * alpha) >> 8;\
*lalphap = ((sa ^ 0xff) * (*lalphap + 1)) >> 8;\
sa++;\
Uint32 d = *dst_buffer & 0xff00ff;\
Uint32 d1 = (d + ((((*src_buffer & 0xff00ff) - d) * sa) >> 8));\
d = *dst_buffer & 0x00ff00;\
Uint32 d2 = (d + ((((*src_buffer & 0x00ff00) - d) * sa) >> 8));\
*dst_buffer = (d1 & 0xff00ff) | (d2 & 0x00ff00) | 0xff000000;\
}\
}
// Originally, the above looks like this.
// mask1 = mask2 ^ 0xff;
// Uint32 mask_rb = (((*dst_buffer & 0xff00ff) * mask1 +
// (*src_buffer & 0xff00ff) * mask2) >> 8) & 0xff00ff;
// Uint32 mask_g = (((*dst_buffer & 0x00ff00) * mask1 +
// (*src_buffer & 0x00ff00) * mask2) >> 8) & 0x00ff00;
#endif
// Dc = Dc + SaSc
#if defined(BPP16)
#define ADDBLEND_PIXEL()\
{\
Uint32 sa = (*alphap * alpha) >> 8;\
sa = (sa + 1) >> 3;\
Uint32 s = (*src_buffer | *src_buffer << 16) & 0x07e0f81f;\
Uint32 d = (*dst_buffer | *dst_buffer << 16) & 0x07e0f81f;\
d = d + (((s * sa) >> 5) & 0x07e0f81f);\
d |= ((d & 0xf8000000) ? 0x07e00000 : 0) |\
((d & 0x001f0000) ? 0x0000f800 : 0) |\
((d & 0x000007e0) ? 0x0000001f : 0);\
d &= 0x07e0f81f;\
*dst_buffer = d | d >> 16;\
alphap++;\
}
#else
#define ADDBLEND_PIXEL()\
{\
Uint32 sa = (((*src_buffer >> 24) * alpha) >> 8) + 1;\
Uint32 d1 = (*dst_buffer & 0xff00ff) + ((((*src_buffer & 0xff00ff) * sa) >> 8) & 0xff00ff);\
d1 |= ((d1 & 0xff000000) ? 0xff0000 : 0) |\
((d1 & 0x0000ff00) ? 0x0000ff : 0);\
Uint32 d2 = (*dst_buffer & 0x00ff00) + (((*src_buffer & 0x00ff00) * sa) >> 8);\
d2 |= ((d2 & 0x00ff0000) ? 0x00ff00 : 0);\
*dst_buffer = (d1 & 0xff00ff) | (d2 & 0x00ff00) | 0xff000000;\
}
#endif
// Dc = Dc - SaSc
#if defined(BPP16)
#define SUBBLEND_PIXEL()\
{\
Uint32 sa = (*alphap * alpha) >> 8;\
sa = (sa + 1) >> 3;\
Uint32 d = (*dst_buffer | *dst_buffer << 16) & 0x07e0f81f;\
Uint32 s = (*src_buffer | *src_buffer << 16) & 0x07e0f81f;\
d = d - (((s * sa) >> 5) & 0x07e0f81f);\
d &= ((d & 0xf8000000) ? 0 : 0x07e00000) |\
((d & 0x001f0000) ? 0 : 0x0000f800) |\
((d & 0x000007e0) ? 0 : 0x0000001f);\
*dst_buffer = d | d >> 16;\
alphap++;\
}
#else
#define SUBBLEND_PIXEL()\
{\
Uint32 sa = (((*src_buffer >> 24) * alpha) >> 8) + 1;\
Uint32 d1 = (*dst_buffer & 0xff00ff) - ((((*src_buffer & 0xff00ff) * sa) >> 8) & 0xff00ff);\
d1 &= ((d1 & 0xff000000) ? 0 : 0xff0000) |\
((d1 & 0x0000ff00) ? 0 : 0x0000ff);\
Uint32 d2 = (*dst_buffer & 0x00ff00) - (((*src_buffer & 0x00ff00) * sa) >> 8); \
d2 &= (d2 & 0x00ff0000) ? 0 : 0x00ff00;\
*dst_buffer = d1 | d2 | 0xff000000;\
}
#endif
// Dc = SaDc + Sc
#if defined(BPP16)
#define ADD2BLEND_PIXEL()\
{\
Uint32 sa = ((*alphap ^ 0xff) + 1) >> 3;\
Uint32 s = (*src_buffer | *src_buffer << 16) & 0x07e0f81f;\
Uint32 d = (*dst_buffer | *dst_buffer << 16) & 0x07e0f81f;\
d = (((d * sa) >> 5) & 0x07e0f81f) + s;\
d |= ((d & 0xf8000000) ? 0x07e00000 : 0) |\
((d & 0x001f0000) ? 0x0000f800 : 0) |\
((d & 0x000007e0) ? 0x0000001f : 0);\
d &= 0x07e0f81f;\
*dst_buffer = d | d >> 16;\
alphap++;\
}
#else
#define ADD2BLEND_PIXEL()\
{\
Uint32 sa = ((*src_buffer >> 24) ^ 0xff) + 1;\
Uint32 d1 = ((((*dst_buffer & 0xff00ff) * sa) >> 8) & 0xff00ff) + (*src_buffer & 0xff00ff);\
d1 |= ((d1 & 0xff000000) ? 0xff0000 : 0) |\
((d1 & 0x0000ff00) ? 0x0000ff : 0);\
Uint32 d2 = ((((*dst_buffer & 0x00ff00) * sa) >> 8) & 0x00ff00) + (*src_buffer & 0x00ff00);\
d2 |= ((d2 & 0x00ff0000) ? 0x00ff00 : 0);\
*dst_buffer = (d1 & 0xff00ff) | (d2 & 0x00ff00) | 0xff000000;\
}
#endif
void AnimationInfo::blendOnSurface( SDL_Surface *dst_surface, int dst_x, int dst_y,
SDL_Rect &clip, unsigned char *layer_alpha_buf, int alpha )
{
if ( image_surface == NULL ) return;
SDL_Rect dst_rect, src_rect;
dst_rect.x = dst_x;
dst_rect.y = dst_y;
dst_rect.w = pos.w;
dst_rect.h = pos.h;
if ( doClipping( &dst_rect, &clip, &src_rect ) ) return;
/* ---------------------------------------- */
SDL_mutexP(mutex);
SDL_LockSurface( dst_surface );
SDL_LockSurface( image_surface );
alpha = (alpha & 0xff) + 1;
int pitch = image_surface->pitch / sizeof(ONSBuf);
ONSBuf *src_buffer = (ONSBuf *)image_surface->pixels + pitch * src_rect.y + image_surface->w*current_cell/num_of_cells + src_rect.x;
ONSBuf *dst_buffer = (ONSBuf *)dst_surface->pixels + dst_surface->w * dst_rect.y + dst_rect.x;
unsigned char *lalphap = layer_alpha_buf + dst_surface->w * dst_rect.y + dst_rect.x;
#if defined(BPP16)
unsigned char *alphap = alpha_buf + image_surface->w * src_rect.y + image_surface->w*current_cell/num_of_cells + src_rect.x;
#endif
for (int i=0 ; i<dst_rect.h ; i++){
for (int j=dst_rect.w ; j!=0 ; j--, src_buffer++, dst_buffer++, lalphap++){
if (trans_mode == AnimationInfo::TRANS_STRING ||
blending_mode == BLEND_ADD2){
ADD2BLEND_PIXEL();
}
else{
BLEND_PIXEL();
}
}
src_buffer += pitch - dst_rect.w;
#if defined(BPP16)
alphap += image_surface->w - dst_rect.w;
#endif
dst_buffer += dst_surface->w - dst_rect.w;
lalphap += dst_surface->w - dst_rect.w;
}
SDL_UnlockSurface( image_surface );
SDL_UnlockSurface( dst_surface );
SDL_mutexV(mutex);
}
void AnimationInfo::blendOnSurface2( SDL_Surface *dst_surface, int dst_x, int dst_y,
SDL_Rect &clip, unsigned char *layer_alpha_buf, int alpha )
{
if ( image_surface == NULL ) return;
if (scale_x == 0 || scale_y == 0) return;
int i, x, y;
// project corner point and calculate bounding box
int min_xy[2]={bounding_rect.x, bounding_rect.y};
int max_xy[2]={bounding_rect.x+bounding_rect.w-1,
bounding_rect.y+bounding_rect.h-1};
// clip bounding box
if (max_xy[0] < clip.x) return;
if (max_xy[0] >= clip.x + clip.w) max_xy[0] = clip.x + clip.w - 1;
if (min_xy[0] >= clip.x + clip.w) return;
if (min_xy[0] < clip.x) min_xy[0] = clip.x;
if (max_xy[1] < clip.y) return;
if (max_xy[1] >= clip.y + clip.h) max_xy[1] = clip.y + clip.h - 1;
if (min_xy[1] >= clip.y + clip.h) return;
if (min_xy[1] < clip.y) min_xy[1] = clip.y;
if (min_xy[1] < 0) min_xy[1] = 0;
if (max_xy[1] >= dst_surface->h) max_xy[1] = dst_surface->h - 1;
SDL_mutexP(mutex);
SDL_LockSurface( dst_surface );
SDL_LockSurface( image_surface );
alpha = (alpha & 0xff) + 1;
int pitch = image_surface->pitch / sizeof(ONSBuf);
int cx2 = affine_pos.x*2 + affine_pos.w; // center x multiplied by 2
int cy2 = affine_pos.y*2 + affine_pos.h; // center y multiplied by 2
int src_rect[2][2]; // clipped source image bounding box
src_rect[0][0] = affine_pos.x;
src_rect[0][1] = affine_pos.y;
src_rect[1][0] = affine_pos.x + affine_pos.w - 1;
src_rect[1][1] = affine_pos.y + affine_pos.h - 1;
if (src_rect[0][0] < 0) src_rect[0][0] = 0;
if (src_rect[0][1] < 0) src_rect[0][1] = 0;
if (src_rect[1][0] >= pos.w) src_rect[1][0] = pos.w - 1;
if (src_rect[1][1] >= pos.h) src_rect[1][1] = pos.h - 1;
// set pixel by inverse-projection with raster scan
for (y=min_xy[1] ; y<= max_xy[1] ; y++){
// calculate the start and end point for each raster scan
int raster_min = min_xy[0], raster_max = max_xy[0];
for (i=0 ; i<4 ; i++){
int i2 = (i+1)&3; // = (i+1)%4
if (corner_xy[i][1] == corner_xy[i2][1]) continue;
x = (corner_xy[i2][0] - corner_xy[i][0])*(y-corner_xy[i][1])/(corner_xy[i2][1] - corner_xy[i][1]) + corner_xy[i][0];
if (corner_xy[i2][1] - corner_xy[i][1] > 0){
if (raster_min < x) raster_min = x;
}
else{
if (raster_max > x) raster_max = x;
}
}
if (raster_min < 0) raster_min = 0;
if (raster_max >= dst_surface->w) raster_max = dst_surface->w - 1;
ONSBuf *dst_buffer = (ONSBuf *)dst_surface->pixels + dst_surface->w * y + raster_min;
unsigned char *lalphap = layer_alpha_buf + dst_surface->w * y + raster_min;
// inverse-projection
int x_offset2 = (inv_mat[0][1] * (y-dst_y) >> 9) + cx2;
int y_offset2 = (inv_mat[1][1] * (y-dst_y) >> 9) + cy2;
for (x=raster_min-dst_x ; x<=raster_max-dst_x ; x++, dst_buffer++, lalphap++){
int x2 = ((inv_mat[0][0] * x >> 9) + x_offset2) >> 1;
int y2 = ((inv_mat[1][0] * x >> 9) + y_offset2) >> 1;
if (x2 < src_rect[0][0] || x2 > src_rect[1][0] ||
y2 < src_rect[0][1] || y2 > src_rect[1][1]) continue;
ONSBuf *src_buffer = (ONSBuf *)image_surface->pixels + pitch * y2 + x2 + pos.w*current_cell;
#if defined(BPP16)
unsigned char *alphap = alpha_buf + image_surface->w * y2 + x2 + pos.w*current_cell;
#endif
if (blending_mode == BLEND_NORMAL){
BLEND_PIXEL();
}
else if (blending_mode == BLEND_ADD){
ADDBLEND_PIXEL();
}
else{
SUBBLEND_PIXEL();
}
}
}
// unlock surface
SDL_UnlockSurface( image_surface );
SDL_UnlockSurface( dst_surface );
SDL_mutexV(mutex);
}
// Da2 = 1-(1-Da)(1-Sa)
// Dc2 = ((1-Sa)DaDc + SaSc)
#if defined(BPP16)
#define BLEND_TEXT_ALPHA()\
{\
Uint32 sa = *src_buffer;\
if (sa == 255){\
*dst_buffer = src_color;\
*alphap = 0xff;\
}\
else if (sa != 0){\
Uint32 da = ((sa ^ 0xff) * (*alphap + 1)) >> 8;\
da = (da + 1) >> 3;\
*alphap = (((sa ^ 0xff) * ((*alphap ^ 0xff) + 1)) >> 8) ^ 0xff;\
sa = (sa + 1) >> 3;\
Uint32 d = (*dst_buffer | *dst_buffer << 16) & 0x07e0f81f;\
d = ((d * da + src_color3 * sa) >> 5) & 0x07e0f81f;\
*dst_buffer = d | d >> 16;\
}\
alphap++;\
}
#else
#define BLEND_TEXT_ALPHA()\
{\
Uint32 sa = *src_buffer;\
if (sa == 255){\
*dst_buffer = src_color;\
}\
else if (sa != 0){\
Uint32 a = *dst_buffer >> 24;\
Uint32 da = (((sa ^ 0xff) * (a + 1)) >> 8) + 1;\
Uint32 da2 = (((sa ^ 0xff) * ((a ^ 0xff) + 1)) >> 8) ^ 0xff;\
sa++;\
Uint32 d1 = ((*dst_buffer & 0xff00ff) * da + src_color1 * sa) >> 8;\
Uint32 d2 = ((*dst_buffer & 0x00ff00) * da + src_color2 * sa) >> 8;\
*dst_buffer = (d1 & 0xff00ff) | (d2 & 0x00ff00) | da2 << 24;\
}\
}
// Originally, the above looks like this.
// Uint32 alpha = *dst_buffer >> 24;
// Uint32 mask1 = ((0xff ^ mask2)*alpha) >> 8;
// alpha = 0xff ^ ((0xff ^ alpha)*(0xff ^ mask2) >> 8);
// Uint32 mask_rb = ((*dst_buffer & 0xff00ff) * mask1 +
// src_color1 * mask2);
// mask_rb = ((mask_rb / alpha) & 0x00ff0000) |
// (((mask_rb & 0xffff) / alpha) & 0xff);
// Uint32 mask_g = (((*dst_buffer & 0x00ff00) * mask1 +
// src_color2 * mask2) / alpha) & 0x00ff00;
// *dst_buffer = mask_rb | mask_g | (alpha << 24);
#endif
// used to draw characters on text_surface
void AnimationInfo::blendText( SDL_Surface *surface, int dst_x, int dst_y, SDL_Color &color,
SDL_Rect *clip, bool rotate_flag )
{
if (image_surface == NULL || surface == NULL) return;
SDL_Rect dst_rect;
dst_rect.x = dst_x;
dst_rect.y = dst_y;
dst_rect.w = surface->w;
dst_rect.h = surface->h;
if (rotate_flag){
dst_rect.w = surface->h;
dst_rect.h = surface->w;
}
SDL_Rect src_rect = {0, 0, 0, 0};
SDL_Rect clipped_rect;
/* ---------------------------------------- */
/* 1st clipping */
if ( clip ){
if ( doClipping( &dst_rect, clip, &clipped_rect ) ) return;
src_rect.x += clipped_rect.x;
src_rect.y += clipped_rect.y;
}
/* ---------------------------------------- */
/* 2nd clipping */
SDL_Rect clip_rect;
clip_rect.x = clip_rect.y = 0;
clip_rect.w = image_surface->w;
clip_rect.h = image_surface->h;
if ( doClipping( &dst_rect, &clip_rect, &clipped_rect ) ) return;
src_rect.x += clipped_rect.x;
src_rect.y += clipped_rect.y;
/* ---------------------------------------- */
SDL_mutexP(mutex);
SDL_LockSurface( surface );
SDL_LockSurface( image_surface );
SDL_PixelFormat *fmt = image_surface->format;
int pitch = image_surface->pitch / sizeof(ONSBuf);
Uint32 src_color1 = (((color.r >> fmt->Rloss) << fmt->Rshift) |
((color.b >> fmt->Bloss) << fmt->Bshift));
Uint32 src_color2 = ((color.g >> fmt->Gloss) << fmt->Gshift);
Uint32 src_color = src_color1 | src_color2;
#if defined(BPP16)
Uint32 src_color3 = (src_color | src_color << 16) & 0x07e0f81f;
#else
src_color |= fmt->Amask;
#endif
ONSBuf *dst_buffer = (ONSBuf *)image_surface->pixels + pitch * dst_rect.y + image_surface->w*current_cell/num_of_cells + dst_rect.x;
#if defined(BPP16)
unsigned char *alphap = alpha_buf + image_surface->w * dst_rect.y + image_surface->w*current_cell/num_of_cells + dst_rect.x;
#endif
if (!rotate_flag){
unsigned char *src_buffer = (unsigned char*)surface->pixels +
surface->pitch*src_rect.y + src_rect.x;
for (int i=dst_rect.h ; i!=0 ; i--){
for (int j=dst_rect.w ; j!=0 ; j--){
BLEND_TEXT_ALPHA();
src_buffer++;
dst_buffer++;
}
dst_buffer += pitch - dst_rect.w;
#if defined(BPP16)
alphap += image_surface->w - dst_rect.w;
#endif
src_buffer += surface->pitch - dst_rect.w;
}
}
else{
for (int i=0 ; i<dst_rect.h ; i++){
unsigned char *src_buffer = (unsigned char*)surface->pixels +
surface->pitch*(surface->h - src_rect.x - 1) + src_rect.y + i;
for (int j=dst_rect.w ; j!=0 ; j--){
BLEND_TEXT_ALPHA();
src_buffer -= surface->pitch;
dst_buffer++;
}
dst_buffer += pitch - dst_rect.w;
#if defined(BPP16)
alphap += image_surface->w - dst_rect.w;
#endif
}
}
SDL_UnlockSurface( image_surface );
SDL_UnlockSurface( surface );
SDL_mutexV(mutex);
}
void AnimationInfo::calcAffineMatrix()
{
// calculate forward matrix
// |mat[0][0] mat[0][1]|
// |mat[1][0] mat[1][1]|
int cos_i = 1024, sin_i = 0;
if (rot != 0){
cos_i = (int)(1024.0 * cos(-M_PI*rot/180));
sin_i = (int)(1024.0 * sin(-M_PI*rot/180));
}
mat[0][0] = cos_i*scale_x/100;
mat[0][1] = -sin_i*scale_y/100;
mat[1][0] = sin_i*scale_x/100;
mat[1][1] = cos_i*scale_y/100;
// calculate bounding box
int min_xy[2] = { 0, 0 }, max_xy[2] = { 0, 0 };
for (int i=0 ; i<4 ; i++){
int c_x = (i<2)?(-affine_pos.w/2):(affine_pos.w/2);
int c_y = ((i+1)&2)?(affine_pos.h/2):(-affine_pos.h/2);
if (scale_x < 0) c_x = -c_x;
if (scale_y < 0) c_y = -c_y;
corner_xy[i][0] = (mat[0][0] * c_x + mat[0][1] * c_y) / 1024 + pos.x;
corner_xy[i][1] = (mat[1][0] * c_x + mat[1][1] * c_y) / 1024 + pos.y;
if (i==0 || min_xy[0] > corner_xy[i][0]) min_xy[0] = corner_xy[i][0];
if (i==0 || max_xy[0] < corner_xy[i][0]) max_xy[0] = corner_xy[i][0];
if (i==0 || min_xy[1] > corner_xy[i][1]) min_xy[1] = corner_xy[i][1];
if (i==0 || max_xy[1] < corner_xy[i][1]) max_xy[1] = corner_xy[i][1];
}
bounding_rect.x = min_xy[0];
bounding_rect.y = min_xy[1];
bounding_rect.w = max_xy[0]-min_xy[0]+1;
bounding_rect.h = max_xy[1]-min_xy[1]+1;
// calculate inverse matrix
int denom = scale_x*scale_y;
if (denom == 0) return;
inv_mat[0][0] = mat[1][1] * 10000 / denom;
inv_mat[0][1] = -mat[0][1] * 10000 / denom;
inv_mat[1][0] = -mat[1][0] * 10000 / denom;
inv_mat[1][1] = mat[0][0] * 10000 / denom;
}
SDL_Surface *AnimationInfo::allocSurface( int w, int h, Uint32 texture_format )
{
SDL_Surface *surface;
if (texture_format == SDL_PIXELFORMAT_RGB565)
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 16, 0xf800, 0x07e0, 0x001f, 0);
else if (texture_format == SDL_PIXELFORMAT_ABGR8888)
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
else // texture_format == SDL_PIXELFORMAT_ARGB8888
surface = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
SDL_SetAlpha(surface, 0, SDL_ALPHA_OPAQUE);
#if defined(USE_SDL_RENDERER) || defined(ANDROID)
SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
#endif
return surface;
}
SDL_Surface *AnimationInfo::alloc32bitSurface( int w, int h, Uint32 texture_format )
{
if (texture_format == SDL_PIXELFORMAT_RGB565)
return allocSurface(w, h, SDL_PIXELFORMAT_ARGB8888);
else
return allocSurface(w, h, texture_format);
}
void AnimationInfo::allocImage( int w, int h, Uint32 texture_format )
{
if (!image_surface ||
image_surface->w != w ||
image_surface->h != h){
deleteSurface(false);
this->texture_format = texture_format;
SDL_mutexP(mutex);
image_surface = allocSurface( w, h, texture_format );
SDL_mutexV(mutex);
#if defined(BPP16)
alpha_buf = new unsigned char[w*h];
#endif
}
abs_flag = true;
pos.w = w / num_of_cells;
pos.h = h;
affine_pos.x = 0;
affine_pos.y = 0;
affine_pos.w = pos.w;
affine_pos.h = pos.h;
}
void AnimationInfo::copySurface( SDL_Surface *surface, SDL_Rect *src_rect, SDL_Rect *dst_rect )
{
if (!image_surface || !surface) return;
SDL_Rect _dst_rect = {0, 0};
if (dst_rect) _dst_rect = *dst_rect;
SDL_Rect _src_rect;
_src_rect.x = _src_rect.y = 0;
_src_rect.w = surface->w;
_src_rect.h = surface->h;
if (src_rect) _src_rect = *src_rect;
if (_src_rect.x >= surface->w) return;
if (_src_rect.y >= surface->h) return;
if (_src_rect.x+_src_rect.w >= surface->w)
_src_rect.w = surface->w - _src_rect.x;
if (_src_rect.y+_src_rect.h >= surface->h)
_src_rect.h = surface->h - _src_rect.y;
if (_dst_rect.x+_src_rect.w > image_surface->w)
_src_rect.w = image_surface->w - _dst_rect.x;
if (_dst_rect.y+_src_rect.h > image_surface->h)
_src_rect.h = image_surface->h - _dst_rect.y;
SDL_mutexP(mutex);
SDL_LockSurface( surface );
SDL_LockSurface( image_surface );
int i;
for (i=0 ; i<_src_rect.h ; i++)
memcpy( (ONSBuf*)((unsigned char*)image_surface->pixels + image_surface->pitch * (_dst_rect.y+i)) + _dst_rect.x,
(ONSBuf*)((unsigned char*)surface->pixels + surface->pitch * (_src_rect.y+i)) + _src_rect.x,
_src_rect.w*sizeof(ONSBuf) );
#if defined(BPP16)
for (i=0 ; i<_src_rect.h ; i++)
memset( alpha_buf + image_surface->w * (_dst_rect.y+i) + _dst_rect.x, 0xff, _src_rect.w );
#endif
SDL_UnlockSurface( image_surface );
SDL_UnlockSurface( surface );
SDL_mutexV(mutex);
}
void AnimationInfo::fill( Uint8 r, Uint8 g, Uint8 b, Uint8 a )
{
if (!image_surface) return;
SDL_mutexP(mutex);
SDL_LockSurface( image_surface );
SDL_PixelFormat *fmt = image_surface->format;
Uint32 rgb = (((r >> fmt->Rloss) << fmt->Rshift) |
((g >> fmt->Gloss) << fmt->Gshift) |
((b >> fmt->Bloss) << fmt->Bshift) |
((a >> fmt->Aloss) << fmt->Ashift));
int pitch = image_surface->pitch / sizeof(ONSBuf);
for (int i=0 ; i<image_surface->h ; i++){
ONSBuf *dst_buffer = (ONSBuf *)image_surface->pixels + pitch*i;
#if defined(BPP16)
unsigned char *alphap = alpha_buf + image_surface->w*i;
#endif
for (int j=0 ; j<image_surface->w ; j++){
*dst_buffer++ = rgb;
#if defined(BPP16)
*alphap++ = a;
#endif
}
}
SDL_UnlockSurface( image_surface );
SDL_mutexV(mutex);
}
SDL_Surface *AnimationInfo::setupImageAlpha( SDL_Surface *surface, SDL_Surface *surface_m, bool has_alpha )
{
if (surface == NULL) return NULL;
SDL_LockSurface( surface );
Uint32 *buffer = (Uint32 *)surface->pixels;
SDL_PixelFormat *fmt = surface->format;
int w = surface->w;
int h = surface->h;
int w2 = w / num_of_cells;
orig_pos.w = w;
orig_pos.h = h;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
unsigned char *alphap = (unsigned char *)buffer + 3;
#else
unsigned char *alphap = (unsigned char *)buffer;
#endif
Uint32 ref_color = 0;
if ( trans_mode == TRANS_TOPLEFT ){
ref_color = *buffer;
}
else if ( trans_mode == TRANS_TOPRIGHT ){
ref_color = *(buffer + surface->w - 1);
}
else if ( trans_mode == TRANS_DIRECT ) {
ref_color =
direct_color[0] << fmt->Rshift |
direct_color[1] << fmt->Gshift |
direct_color[2] << fmt->Bshift;
}
ref_color &= 0xffffff;
int i, j, c;
if ( trans_mode == TRANS_ALPHA && !has_alpha ){
const int w22 = w2/2;
const int w3 = w22 * num_of_cells;
orig_pos.w = w3;
SDL_PixelFormat *fmt = surface->format;
SDL_Surface *surface2 = SDL_CreateRGBSurface( SDL_SWSURFACE, w3, h,
fmt->BitsPerPixel, fmt->Rmask, fmt->Gmask, fmt->Bmask, fmt->Amask );
SDL_LockSurface( surface2 );
Uint32 *buffer2 = (Uint32 *)surface2->pixels;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
alphap = (unsigned char *)buffer2 + 3;
#else
alphap = (unsigned char *)buffer2;
#endif
for (i=h ; i!=0 ; i--){
for (c=num_of_cells ; c!=0 ; c--){
for (j=w22 ; j!=0 ; j--, buffer++, alphap+=4){
*buffer2++ = *buffer;
*alphap = (*(buffer + w22) & 0xff) ^ 0xff;
}
buffer += (w2 - w22);
}
buffer += surface->w - w2 *num_of_cells;
buffer2 += surface2->w - w22*num_of_cells;
alphap += (surface2->w - w22*num_of_cells)*4;
}
SDL_UnlockSurface( surface );
SDL_FreeSurface( surface );
surface = surface2;
}
else if ( trans_mode == TRANS_MASK ){
if (surface_m){
SDL_LockSurface( surface_m );
const int mw = surface_m->w;
const int mwh = surface_m->w * surface_m->h;
int i2 = 0;
for (i=h ; i!=0 ; i--){
Uint32 *buffer_m = (Uint32 *)surface_m->pixels + i2;
for (c=num_of_cells ; c!=0 ; c--){
int j2 = 0;
for (j=w2 ; j!=0 ; j--, buffer++, alphap+=4){
*alphap = (*(buffer_m + j2) & 0xff) ^ 0xff;
if (j2 >= mw) j2 = 0;
else j2++;
}
}
if (i2 >= mwh) i2 = 0;
else i2 += mw;
}
SDL_UnlockSurface( surface_m );
}
}
else if ( trans_mode == TRANS_TOPLEFT ||
trans_mode == TRANS_TOPRIGHT ||
trans_mode == TRANS_DIRECT ){
for (i=h ; i!=0 ; i--){
for (j=w ; j!=0 ; j--, buffer++, alphap+=4){
if ( (*buffer & 0xffffff) == ref_color )
*alphap = 0x00;
else
*alphap = 0xff;
}
}
}
else if ( trans_mode == TRANS_STRING ){
for (i=h ; i!=0 ; i--){
for (j=w ; j!=0 ; j--, buffer++, alphap+=4)
*alphap = *buffer >> 24;
}
}
else if ( trans_mode != TRANS_ALPHA ){ // TRANS_COPY
for (i=h ; i!=0 ; i--){
for (j=w ; j!=0 ; j--, buffer++, alphap+=4)
*alphap = 0xff;
}
}
SDL_UnlockSurface( surface );
return surface;
}
void AnimationInfo::setImage( SDL_Surface *surface, Uint32 texture_format )
{
if (surface == NULL) return;
this->texture_format = texture_format;
#if !defined(BPP16)
image_surface = surface; // deleteSurface() should be called beforehand
#endif
allocImage(surface->w, surface->h, texture_format);
#if defined(BPP16)
SDL_LockSurface( surface );
unsigned char *alphap = alpha_buf;
for (int i=0 ; i<surface->h ; i++){
ONSBuf *dst_buffer = (ONSBuf *)((unsigned char*)image_surface->pixels + image_surface->pitch*i);
Uint32 *buffer = (Uint32 *)((unsigned char*)surface->pixels + surface->pitch*i);
for (int j=0 ; j<surface->w ; j++, buffer++){
// ARGB8888 -> RGB565 + alpha
*dst_buffer++ = ((((*buffer)&0xf80000) >> 8) |
(((*buffer)&0x00fc00) >> 5) |
(((*buffer)&0x0000f8) >> 3));
*alphap++ = ((*buffer) >> 24);
}
}
SDL_UnlockSurface( surface );
SDL_FreeSurface( surface );
#endif
}
unsigned char AnimationInfo::getAlpha(int x, int y)
{
if (image_surface == NULL) return 0;
x -= pos.x;
y -= pos.y;
int offset_x = (image_surface->w/num_of_cells)*current_cell;
unsigned char alpha = 0;
#if defined(BPP16)
alpha = alpha_buf[image_surface->w*y+offset_x+x];
#else
int pitch = image_surface->pitch / 4;
SDL_mutexP(mutex);
SDL_LockSurface( image_surface );
ONSBuf *buf = (ONSBuf *)image_surface->pixels + pitch*y + offset_x + x;
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
alpha = *((unsigned char *)buf + 3);
#else
alpha = *((unsigned char *)buf);
#endif
SDL_UnlockSurface( image_surface );
SDL_mutexV(mutex);
#endif
return alpha;
}
void AnimationInfo::convertFromYUV(SDL_Overlay *src)
{
SDL_mutexP(mutex);
if (!image_surface){
SDL_mutexV(mutex);
return;
}
SDL_Surface *ls = image_surface;
SDL_LockSurface(ls);
SDL_PixelFormat *fmt = ls->format;
for (int i=0 ; i<ls->h ; i++){
int i2 = src->h*i/ls->h;
int i3 = (src->h/2)*i/ls->h;
Uint8 *y = src->pixels[0]+src->pitches[0]*i2;
Uint8 *v = src->pixels[1]+src->pitches[1]*i3;
Uint8 *u = src->pixels[2]+src->pitches[2]*i3;
ONSBuf *p = (ONSBuf*)ls->pixels + (ls->pitch/sizeof(ONSBuf))*i;
for (int j=0 ; j<ls->w ; j++){
int j2 = src->w*j/ls->w;
int j3 = (src->w/2)*j/ls->w;
Sint32 y2 = *(y+j2);
Sint32 u2 = *(u+j3)-128;
Sint32 v2 = *(v+j3)-128;
//Sint32 r = 1.0*y2 + 1.402*v2;
//Sint32 g = 1.0*y2 - 0.344*u2 - 0.714*v2;
//Sint32 b = 1.0*y2 + 1.772*u2;
y2 <<= 10;
Sint32 r = y2 + 1436*v2;
Sint32 g = y2 - 352*u2 - 731*v2;
Sint32 b = y2 + 1815*u2;
if (r < 0) r = 0;
if (g < 0) g = 0;
if (b < 0) b = 0;
*(p+j) =
(((r >> (10+fmt->Rloss)) & 0xff) << fmt->Rshift) |
(((g >> (10+fmt->Gloss)) & 0xff) << fmt->Gshift) |
(((b >> (10+fmt->Bloss)) & 0xff) << fmt->Bshift) |
fmt->Amask;
}
}
SDL_UnlockSurface(ls);
#if defined(BPP16)
memset(alpha_buf, 0xff, ls->w*ls->h);
#endif
SDL_mutexV(mutex);
}
// Da = 1 - Sa2
// Dc = (Sc1 - Sa2Sc2)/Da
// so that Sc1 = (1-Sa2)Dc + Sa2Sc2
#if defined(BPP16)
#define SUBTRACT_PIXEL()\
{\
Uint32 sa2 = *lalphap;\
*alphap++ = sa2 ^ 0xff;\
sa2 = (sa2 + 1) >> 3;\
Uint32 s1 = (*src1_buffer | *src1_buffer << 16) & 0x07e0f81f;\
Uint32 s2 = (*src2_buffer | *src2_buffer << 16) & 0x07e0f81f;\
Uint32 d = s1 - (((s2 * sa2) >> 5) & 0x07e0f81f);\
d &= ((d & 0xf8000000) ? 0 : 0x07e00000) |\
((d & 0x001f0000) ? 0 : 0x0000f800) |\
((d & 0x000007e0) ? 0 : 0x0000001f);\
*dst_buffer = d | d >> 16;\
}
#else
#define SUBTRACT_PIXEL()\
{\
Uint32 sa = *lalphap;\
Uint32 da = (sa ^ 0xff);\
sa++;\
Uint32 d1 = (*src1_buffer & 0xff00ff) - ((((*src2_buffer & 0xff00ff) * sa) >> 8) & 0xff00ff);\
d1 &= ((d1 & 0xff000000) ? 0 : 0xff0000) |\
((d1 & 0x0000ff00) ? 0 : 0x0000ff);\
Uint32 d2 = (*src1_buffer & 0x00ff00) - (((*src2_buffer & 0x00ff00) * sa) >> 8);\
d2 &= (d2 & 0x00ff0000) ? 0 : 0x00ff00;\
*dst_buffer = d1 | d2 | da << 24;\
}
#endif
// effect_src_info = (surface(accumulation_surface) - layer_alpha * layer_info)/(0xff ^ layer_alpha)
// effect_src_info.alpha = 0xff ^ layer_alpha
void AnimationInfo::subtract(SDL_Surface *surface, AnimationInfo *layer_info,
unsigned char *layer_alpha_buf)
{
if (image_surface == NULL || layer_info->image_surface == NULL) return;
SDL_mutexP(mutex);
SDL_mutexP(layer_info->mutex);
SDL_LockSurface(surface);
SDL_LockSurface(image_surface);
SDL_LockSurface(layer_info->image_surface);
ONSBuf *dst_buffer = (ONSBuf *)image_surface->pixels;
ONSBuf *src1_buffer = (ONSBuf *)surface->pixels;
ONSBuf *src2_buffer = (ONSBuf *)layer_info->image_surface->pixels;
unsigned char *lalphap = layer_alpha_buf;
#if defined(BPP16)
unsigned char *alphap = alpha_buf;
#endif
for (int i=0 ; i<surface->h ; i++){
for (int j=surface->w; j!=0; j--, dst_buffer++, src1_buffer++, src2_buffer++, lalphap++){
SUBTRACT_PIXEL();
}
}
SDL_UnlockSurface(layer_info->image_surface);
SDL_UnlockSurface(image_surface);
SDL_UnlockSurface(surface);
SDL_mutexV(layer_info->mutex);
SDL_mutexV(mutex);
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/weimingtom/Onscripter-Official.git
git@gitee.com:weimingtom/Onscripter-Official.git
weimingtom
Onscripter-Official
Onscripter-Official
master

搜索帮助