1 /* === S I N F G =========================================================== */
2 /*! \file surfacenew.cpp
3 ** \brief Template File
5 ** $Id: surfacenew.cpp,v 1.1 2005/01/21 19:29:10 darco Exp $
8 ** Copyright (c) 2002 Robert B. Quattlebaum Jr.
10 ** This software and associated documentation
11 ** are CONFIDENTIAL and PROPRIETARY property of
12 ** the above-mentioned copyright holder.
14 ** You may not copy, print, publish, or in any
15 ** other way distribute this software without
16 ** a prior written agreement with
17 ** the copyright holder.
20 /* ========================================================================= */
22 /* === H E A D E R S ======================================================= */
31 #include "surfacenew.h"
32 #include <ETL/ref_count>
37 /* === U S I N G =========================================================== */
41 using namespace sinfg;
43 /* === M A C R O S ========================================================= */
45 /* === G L O B A L S ======================================================= */
47 /* === P R O C E D U R E S ================================================= */
49 /* === C L A S S E S & S T R U C T S ======================================= */
51 class SurfaceNew::ChannelData
54 etl::reference_counter ref_count_;
76 if(ref_count_.unique())
80 void set_wh(int w, int h)
86 if(data_&&ref_count_.is_unique())
89 ref_count.make_unique();
90 data_=new float [w_*h_];
95 void crop(int x, int y, int w, int h)
97 origin_=origin+y*stride_+x;
102 int get_stride()const
110 bzero(origin_+stride_*i,w_*sizeof(float));
115 float* ptr(get_data());
117 for(int y=0;y<h;y++,ptr+=stride_)
118 for(int i=0;i<w_;i++)
122 float* get_data() { return origin_; }
126 if(!ref_count_.unique())
128 ref_count_.make_unique();
129 float* old_data(origin_);
132 data_=new float [w_*h_];
137 memcpy(data_+i*stride_,old_data+i*old_stride,sizeof(float)*w_);
140 }; // END of class ChannelData
142 /* === M E T H O D S ======================================================= */
144 SurfaceNew::SurfaceNew():
147 color_system_(COLORSYS_RGB),
152 SurfaceNew~SurfaceNew()
157 SurfaceNew::create(int w, int h, ColorSystem sys=COLORSYS_RGB)
159 Handle ret(new SurfaceNew);
162 ret.set_color_system(sys);
168 SurfaceNew::create(const Surface&)
175 SurfaceNew::create(HandleConst orig)
179 Handle ret(new SurfaceNew);
183 ret.color_system_=orig.color_system_;
184 ret.premult_flag_=orig.premult_flag_;
185 ret.channel_map_=orig.channel_map_;
191 SurfaceNew::crop(HandleConst, int x, int y, int w, int h)
195 Handle ret(new SurfaceNew);
199 ret.color_system_=orig.color_system_;
200 ret.premult_flag_=orig.premult_flag_;
201 ret.channel_map_=orig.channel_map_;
203 std::map<Channel,ChannelData>::iterator iter;
204 for(iter=ret.channel_map_.begin();iter!=ret.channel_map_.end();++iter)
211 SurfaceNew::get_w()const
217 SurfaceNew::get_h()const
223 SurfaceNew::set_wh(int w, int h)
229 channel_map_.clear();
233 SurfaceNew::ColorSystem
234 SurfaceNew::get_color_system()const
236 return color_system_;
240 SurfaceNew::set_color_system(SurfaceNew::ColorSystem x)
246 SurfaceNew::get_color(int x, int y)const
248 // This operation is rather expensive, as it should be.
249 // I want to discurage people from using it all over the place.
252 lock_channel_const(CHAN_R).get_value(x,y),
253 lock_channel_const(CHAN_G).get_value(x,y),
254 lock_channel_const(CHAN_B).get_value(x,y),
255 lock_channel_const(CHAN_A).get_value(x,y)
260 ret=ret.demult_alpha();
279 SurfaceNew::trylock()
281 return mutex_.trylock();
284 SurfaceNew::ChannelLock
285 SurfaceNew::lock_channel(SurfaceNew::Channel chan)
287 if(!is_channel_defined(chan)
288 channel_map_[chan].set_wh(get_w(),get_h());
290 channel_map_[chan].make_unique();
292 ChannelLockConst channel_lock;
294 channel_lock.surface_=this;
295 channel_lock.channel_=chan;
297 channel_map_[chan].rw_lock.writer_lock();
302 SurfaceNew::ChannelLockConst
303 SurfaceNew::lock_channel_const(SurfaceNew::Channel chan)const
305 if(!is_channel_defined(chan)
306 channel_map_[chan].set_wh(get_w(),get_h());
308 ChannelLockConst channel_lock;
310 channel_lock.surface_=this;
311 channel_lock.channel_=chan;
313 channel_map_[chan].rw_lock.reader_lock();
318 SurfaceNew::ChannelLock
319 SurfaceNew::lock_channel_alpha(SurfaceNew::Channel chan)
321 // Change this when per-channel alpha
323 return lock_channel(CHAN_A);
326 SurfaceNew::ChannelLockConst
327 SurfaceNew::lock_channel_alpha_const(SurfaceNew::Channel chan)const
329 // Change this when per-channel alpha
331 return lock_channel_const(CHAN_A);
335 SurfaceNew::is_channel_defined(Channel chan)const
337 return channel_map_.count(chan);
341 SurfaceNew::get_premult()const
343 return premult_flag_;
347 SurfaceNew::set_premult(bool x)
357 if(get_color_system()==COLORSYS_RGB)switch(i)
364 if(get_color_system()==COLORSYS_YUV)switch(i)
371 // If this channel isn't defined, then
372 // skip it and move on to the next one
373 if(!is_channel_defined(chan))
376 ChannelLock color_channel(lock_channel(chan));
377 ChannelLockConst alpha_channel(lock_channel_alpha_const(chan));
378 const int w(get_w());
379 const int h(get_h());
381 float* color_ptr(color_channel.get_data_ptr());
382 const float* alpha_ptr(alpha_channel.get_data_ptr());
384 const int color_pitch(color_channel.get_data_ptr_stride()-w);
385 const int alpha_pitch(alpha_channel.get_data_ptr_stride()-w);
389 for(int y=0;y<h;y++,color_ptr+=color_pitch,alpha_ptr+=alpha_pitch)
390 for(int x=0;x<w;x++,color_ptr++,alpha_ptr++)
391 *color_ptr *= *alpha_ptr;
395 for(int y=0;y<h;y++,color_ptr+=color_pitch,alpha_ptr+=alpha_pitch)
396 for(int x=0;x<w;x++,color_ptr++,alpha_ptr++)
397 *color_ptr /= *alpha_ptr;
404 Handle dest, int x_dest, int y_dest,
405 HandleConst src, int x_src, int y_src, int w_src, int h_src,
406 float amount=1.0, Color::BlendMethod bm=Color::BLEND_COMPOSITE
427 Handle dest, int x_dest, int y_dest,
429 float amount=1.0, Color::BlendMethod bm=Color::BLEND_COMPOSITE
432 int w(src->get_w()), h(src->get_h);
438 if(x_dest+w>dest.get_w())
439 w=dest.get_w()-x_dest;
440 if(y_dest+h>dest.get_h())
441 h=dest.get_h()-y_dest;
452 src=crop(src,x,y,w,h);
455 dest=crop(dest,x_dest,y_dest,w,h);
457 if(bm==Color::BLEND_STRAIGHT)
459 chan_mlt(dest,amount/(1.0-amount));
461 chan_mlt(dest,(1.0-amount)/amount);
464 if(bm==Color::BLEND_COMPOSITE)
472 // -----------------------------------------------------------------------------------
474 SurfaceChannelLockConst::SurfaceChannelLockConst():
475 data_ptr_checked_out_(false)
479 SurfaceChannelLockConst::~SurfaceChannelLockConst()
481 if(data_ptr_checked_out_)
484 if(surface_ && ref_count_.is_unique())
485 return surface->channel_map_[channel_].rw_lock.reader_unlock();
490 SurfaceChannelLockConst::get_channel()const
496 SurfaceChannelLockConst::get_w()const
498 return surface_->get_w();
502 SurfaceChannelLockConst::get_h()const
504 return surface_->get_h();
508 SurfaceChannelLockConst::get_value(int x, int y)
511 const ChannelData& channel_data(surface_->channel_map_[channel_]);
512 return *(channel_data.get_data()+y*channel_data.get_stride()+x);
516 SurfaceChannelLockConst::get_data_ptr()const
518 data_ptr_checked_out_=true;
521 return surface_->channel_map_[channel_].get_data();
525 SurfaceChannelLockConst::get_data_ptr_stride()const
527 return surface_->channel_map_[channel_].get_stride();
531 SurfaceChannelLockConst::release_data_ptr()const
533 data_ptr_checked_out_=false;
536 SurfaceChannelLockConst::operator bool()const
538 return static_cast<bool>(surface_);
541 // -----------------------------------------------------------------------------------
543 SurfaceChannelLock::SurfaceChannelLock()
547 SurfaceChannelLock::~SurfaceChannelLock()
549 if(data_ptr_checked_out_)
552 if(surface_ && ref_count_.is_unique())
553 return surface_->channel_map_[channel_].rw_lock.writer_unlock();
558 SurfaceChannelLock::clear()
560 return surface_->channel_map_[channel_].clear();
564 SurfaceChannelLock::fill(float v)
566 return surface_->channel_map_[channel_].fill(v);
570 SurfaceChannelLock::set_value(int x, int y, float v)
573 const ChannelData& channel_data(surface_->channel_map_[channel_]);
574 *(channel_data.get_data()+y*channel_data.get_stride()+x)=v;
578 SurfaceChannelLock::get_data_ptr()
580 data_ptr_checked_out_=true;
583 return surface_->channel_map_[channel_].get_data();
588 // -----------------------------------------------------------------------------------
593 SurfaceNew::chan_mlt(ChannelLock& dest, float x)
595 float* ptr(dest.get_data_ptr());
596 const int w(dest.get_w());
597 const int h(dest.get_h());
598 const int pitch(dest.get_data_pitch()-w);
600 int(y=0;y<h;y++,ptr+=pitch)
601 int(x=0;x<w;x++,ptr++)
606 SurfaceNew::chan_mlt(ChannelLock& dest, const ChannelLockConst& x)
608 float* d_ptr(dest.get_data_ptr());
609 const float* s_ptr(x.get_data_ptr());
610 const int w(dest.get_w());
611 const int h(dest.get_h());
612 const int d_pitch(dest.get_data_stride()-w);
613 const int s_pitch(x.get_data_stride()-w);
615 int(y=0;y<h;y++,d_ptr+=d_pitch,s_ptr+=s_pitch)
616 int(x=0;x<w;x++,d_ptr++,s_ptr++)
621 SurfaceNew::chan_div(ChannelLock& dest, float x)
623 float* ptr(dest.get_data_ptr());
624 const int w(dest.get_w());
625 const int h(dest.get_h());
626 const int pitch(dest.get_data_pitch()-w);
628 int(y=0;y<h;y++,ptr+=pitch)
629 int(x=0;x<w;x++,ptr++)
634 SurfaceNew::chan_div(ChannelLock& dest, const ChannelLockConst& x)
636 float* d_ptr(dest.get_data_ptr());
637 const float* s_ptr(x.get_data_ptr());
638 const int w(dest.get_w());
639 const int h(dest.get_h());
640 const int d_pitch(dest.get_data_stride()-w);
641 const int s_pitch(x.get_data_stride()-w);
643 int(y=0;y<h;y++,d_ptr+=d_pitch,s_ptr+=s_pitch)
644 int(x=0;x<w;x++,d_ptr++,s_ptr++)
649 SurfaceNew::chan_add(ChannelLock& dest, float x)
651 float* ptr(dest.get_data_ptr());
652 const int w(dest.get_w());
653 const int h(dest.get_h());
654 const int pitch(dest.get_data_pitch()-w);
656 int(y=0;y<h;y++,ptr+=pitch)
657 int(x=0;x<w;x++,ptr++)
662 SurfaceNew::chan_add(ChannelLock& dest, const ChannelLockConst& x)
664 float* d_ptr(dest.get_data_ptr());
665 const float* s_ptr(x.get_data_ptr());
666 const int w(dest.get_w());
667 const int h(dest.get_h());
668 const int d_pitch(dest.get_data_stride()-w);
669 const int s_pitch(x.get_data_stride()-w);
671 int(y=0;y<h;y++,d_ptr+=d_pitch,s_ptr+=s_pitch)
672 int(x=0;x<w;x++,d_ptr++,s_ptr++)
677 SurfaceNew::chan_sub(ChannelLock& dest, float x)
679 float* ptr(dest.get_data_ptr());
680 const int w(dest.get_w());
681 const int h(dest.get_h());
682 const int pitch(dest.get_data_pitch()-w);
684 int(y=0;y<h;y++,ptr+=pitch)
685 int(x=0;x<w;x++,ptr++)
690 SurfaceNew::chan_sub(ChannelLock& dest, const ChannelLockConst& x)
692 float* d_ptr(dest.get_data_ptr());
693 const float* s_ptr(x.get_data_ptr());
694 const int w(dest.get_w());
695 const int h(dest.get_h());
696 const int d_pitch(dest.get_data_stride()-w);
697 const int s_pitch(x.get_data_stride()-w);
699 int(y=0;y<h;y++,d_ptr+=d_pitch,s_ptr+=s_pitch)
700 int(x=0;x<w;x++,d_ptr++,s_ptr++)