Adobe Systems, Inc.

algorithm.hpp

Go to the documentation of this file.
00001 /*
00002     Copyright 2005-2006 Adobe Systems Incorporated
00003     Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
00004     or a copy at http://opensource.adobe.com/licenses.html)
00005 */
00006 
00007 /*************************************************************************************************/
00008 
00009 #ifndef GIL_ALGORITHMS_H
00010 #define GIL_ALGORITHMS_H
00011 
00012 #include <cassert>
00013 #include <cstddef>
00014 #include <algorithm>
00015 #include "gil_config.hpp"
00016 #include "gil_concept.hpp"
00017 #include "pixel_algorithm.hpp"
00018 #include "image_view.hpp"
00019 #include "image_view_factory.hpp"
00020 
00029 
00030 ADOBE_GIL_NAMESPACE_BEGIN
00031 
00032 // a tag denoting incompatible arguments
00033 struct error_t {};
00034 
00035 /*
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00047 template <typename ARG, typename UNARY_OP> GIL_FORCEINLINE
00048 typename UNARY_OP::result_type apply_operation(const ARG& arg, UNARY_OP op) {
00049     typedef typename detail::reduce<UNARY_OP,ARG>::type base_t;
00050     return op(reinterpret_cast<const base_t&>(arg));
00051 }
00052 
00054 template <typename ARG, typename UNARY_OP> GIL_FORCEINLINE
00055 typename UNARY_OP::result_type apply_operation(ARG& arg, UNARY_OP op) {
00056     typedef typename detail::reduce<UNARY_OP,ARG>::type base_t;
00057     return op(reinterpret_cast<base_t&>(arg));
00058 }
00059 
00061 template <typename ARG1, typename ARG2, typename BINARY_OP> GIL_FORCEINLINE
00062 typename BINARY_OP::result_type apply_operation(const ARG1& arg1, const ARG2& arg2, BINARY_OP op) {
00063     typedef typename detail::reduce<BINARY_OP,ARG1>::type base1_t;
00064     typedef typename detail::reduce<BINARY_OP,ARG2>::type base2_t;
00065     typedef std::pair<const base1_t*, const base2_t*> pair_t;
00066     typedef typename detail::reduce<BINARY_OP,pair_t>::type base_pair_t;
00067 
00068     std::pair<const void*, const void*> p(&arg1, &arg2);
00069     return op(reinterpret_cast<const base_pair_t&>(p));
00070 }
00072 */
00073 
00082 template <typename DERIVED, typename RESULT_T=void>
00083 struct binary_operation_obj {
00084     typedef RESULT_T result_type;
00085 
00086     template <typename V1, typename V2> GIL_FORCEINLINE
00087     result_type operator()(const std::pair<const V1*,const V2*>& p) const {
00088         return apply(*p.first, *p.second, typename views_are_compatible<V1,V2>::type());
00089     }
00090 
00091      template <typename V1, typename V2> GIL_FORCEINLINE
00092      result_type operator()(const V1& v1, const V2& v2) const {
00093         return apply(v1, v2, typename views_are_compatible<V1,V2>::type());
00094     }
00095 
00096     result_type operator()(const error_t&) const { throw std::bad_cast(); }
00097 private:
00098 
00099     // dispatch from apply overload to a function with distinct name
00100     template <typename V1, typename V2>
00101     GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, boost::mpl::false_) const {
00102         return ((const DERIVED*)this)->apply_incompatible(v1,v2);
00103     }
00104 
00105     // dispatch from apply overload to a function with distinct name
00106     template <typename V1, typename V2>
00107     GIL_FORCEINLINE result_type apply(const V1& v1, const V2& v2, boost::mpl::true_) const {
00108         return ((const DERIVED*)this)->apply_compatible(v1,v2);
00109     }
00110 
00111     // function with distinct name - it can be overloaded by subclasses
00112     template <typename V1, typename V2>
00113     GIL_FORCEINLINE result_type apply_incompatible(const V1& v1, const V2& v2) const {
00114         throw std::bad_cast();
00115     }
00116 };
00117 ADOBE_GIL_NAMESPACE_END
00118 
00124 
00128 
00129 namespace std {
00133 
00136     template<typename T, typename CS> 
00137     GIL_FORCEINLINE GIL::pixel<T,CS>* copy(GIL::pixel<T,CS>* first, GIL::pixel<T,CS>* last, GIL::pixel<T,CS>* dst) { 
00138         return (GIL::pixel<T,CS>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
00139     }
00140 
00143     template<typename T, typename CS> 
00144     GIL_FORCEINLINE GIL::pixel<T,CS>* copy(const GIL::pixel<T,CS>* first, const GIL::pixel<T,CS>* last, GIL::pixel<T,CS>* dst) { 
00145         return (GIL::pixel<T,CS>*)std::copy((unsigned char*)first,(unsigned char*)last, (unsigned char*)dst);
00146     }
00147 }
00148 
00149 ADOBE_GIL_NAMESPACE_BEGIN
00150 namespace detail {
00151     template <typename I, typename O> struct copy_fn { 
00152         GIL_FORCEINLINE I operator()(I first, I last, O dst) const { return std::copy(first,last,dst); } 
00153     };
00154 }
00155 ADOBE_GIL_NAMESPACE_END
00156 
00157 namespace std {
00160     template<typename IC1, typename CS1, typename IC2, typename CS2> GIL_FORCEINLINE
00161     GIL::planar_ptr<IC2,CS2> copy(GIL::planar_ptr<IC1,CS1> first, GIL::planar_ptr<IC1,CS1> last, GIL::planar_ptr<IC2,CS2> dst) { 
00162         GIL::gil_function_requires<GIL::ChannelsCompatibleConcept<typename std::iterator_traits<IC1>::value_type,typename std::iterator_traits<IC2>::value_type> >();
00163         GIL::gil_function_requires<GIL::ColorSpacesCompatibleConcept<CS1,CS2> >();
00164         for_each_channel(first,last,dst,GIL::detail::copy_fn<IC1,IC2>());
00165         return dst+(last-first);
00166     }
00167 }
00168 
00169 ADOBE_GIL_NAMESPACE_BEGIN
00170 namespace detail {
00173     template <typename I, typename O>
00174     struct copier_n {
00175         GIL_FORCEINLINE void operator()(I src, std::ptrdiff_t n, O dst) const { std::copy(src,src+n, dst); }
00176     };
00177 
00180     template <typename IL, typename O>  // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
00181     struct copier_n<GIL::pixel_image_iterator<IL>,O> {
00182         GIL_FORCEINLINE void operator()(GIL::pixel_image_iterator<IL> src, std::ptrdiff_t n, O dst) const {
00183             GIL::gil_function_requires<GIL::PixelLocatorConcept<IL> >();
00184             GIL::gil_function_requires<GIL::MutablePixelIteratorConcept<O> >();
00185             while (n>0) {
00186                 std::ptrdiff_t numToCopy=std::min<const std::ptrdiff_t>(n, src.width()-src.x_pos());
00187                 adobe::copy_n(src.x(), numToCopy, dst);
00188                 dst+=numToCopy;
00189                 src+=numToCopy;
00190                 n-=numToCopy;
00191             }
00192         }
00193     };
00194 
00197     template <typename I, typename OL> // I Models ConstPixelIteratorConcept, OL Models PixelLocatorConcept
00198     struct copier_n<I,GIL::pixel_image_iterator<OL> > {
00199         GIL_FORCEINLINE void operator()(I src, std::ptrdiff_t n, GIL::pixel_image_iterator<OL> dst) const {
00200             GIL::gil_function_requires<GIL::PixelIteratorConcept<I> >();
00201             GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<OL> >();
00202             while (n>0) {
00203                 std::ptrdiff_t numToCopy=std::min<const std::ptrdiff_t>(n,dst.width()-dst.x_pos());
00204                 adobe::copy_n(src, numToCopy, dst.x());
00205                 dst+=numToCopy;
00206                 src+=numToCopy;
00207                 n-=numToCopy;
00208             }
00209         }
00210     };
00211 
00214     template <typename IL, typename OL>
00215     struct copier_n<GIL::pixel_image_iterator<IL>,GIL::pixel_image_iterator<OL> > {
00216        GIL_FORCEINLINE void operator()(GIL::pixel_image_iterator<IL> src, std::ptrdiff_t n, GIL::pixel_image_iterator<OL> dst) const {
00217             GIL::gil_function_requires<GIL::PixelLocatorConcept<IL> >();
00218             GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<OL> >();
00219             if (src.x_pos()!=dst.x_pos() || src.width()!=dst.width()) {
00220                 while(n-->0) {
00221                     *dst++=*src++;
00222                 }
00223             }
00224             while (n>0) {
00225                 std::ptrdiff_t numToCopy=std::min<const std::ptrdiff_t>(n,dst.width()-dst.x_pos());
00226                 adobe::copy_n(src.x(), numToCopy, dst.x());
00227                 dst+=numToCopy;
00228                 src+=numToCopy;
00229                 n-=numToCopy;
00230             }
00231         }
00232     };
00233 }
00234 ADOBE_GIL_NAMESPACE_END
00235 
00236 namespace std {
00248     template <typename IL, typename OL>
00249     GIL_FORCEINLINE GIL::pixel_image_iterator<OL> copy(GIL::pixel_image_iterator<IL> first, GIL::pixel_image_iterator<IL> last, GIL::pixel_image_iterator<OL> dst) {
00250         GIL::gil_function_requires<GIL::PixelLocatorConcept<IL> >();
00251         GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<OL> >();
00252         std::ptrdiff_t n=last-first;
00253         if (first.is_contiguous()) {
00254             if (dst.is_contiguous())
00255                 GIL::detail::copier_n<typename IL::x_iterator,typename OL::x_iterator>()(first.x(),n, dst.x());
00256             else
00257                 GIL::detail::copier_n<typename IL::x_iterator,GIL::pixel_image_iterator<OL> >()(first.x(),n, dst);
00258         } else {
00259             if (dst.is_contiguous())
00260                 GIL::detail::copier_n<GIL::pixel_image_iterator<IL>,typename OL::x_iterator>()(first,n, dst.x());
00261             else
00262                 GIL::detail::copier_n<GIL::pixel_image_iterator<IL>,GIL::pixel_image_iterator<OL> >()(first,n,dst);
00263         }
00264         return dst+n;
00265     }
00266 }
00267 
00268 ADOBE_GIL_NAMESPACE_BEGIN
00269 
00270 
00273 template <typename V1, typename V2> GIL_FORCEINLINE
00274 void copy_pixels(const V1& src, const V2& dst) { 
00275     assert(src.dimensions()==dst.dimensions());
00276     std::copy(src.begin(),src.end(),dst.begin());   // std::copy will choose the optimal method (see stl_override.h)
00277 }
00278 ADOBE_GIL_NAMESPACE_END
00279 
00285 
00289 
00290 ADOBE_GIL_NAMESPACE_BEGIN
00291 namespace detail {
00292     struct copy_and_convert_pixels_fn : public binary_operation_obj<copy_and_convert_pixels_fn> {
00293        // when the two color spaces are incompatible, a color conversion is performed
00294         template <typename V1, typename V2> GIL_FORCEINLINE 
00295         result_type apply_incompatible(const V1& src, const V2& dst) const {
00296             copy_pixels(color_converted_view<typename V2::value_type>(src),dst);
00297         }
00298 
00299         // If the two color spaces are compatible, copy_and_convert is just copy
00300         template <typename V1, typename V2> GIL_FORCEINLINE 
00301         result_type apply_compatible(const V1& src, const V2& dst) const {
00302              copy_pixels(src,dst);
00303         }
00304     };
00305 }
00306 
00309 template <typename V1, typename V2> GIL_FORCEINLINE 
00310 void copy_and_convert_pixels(const V1& src, const V2& dst) { 
00311     detail::copy_and_convert_pixels_fn()(src,dst);
00312 }
00313 
00314 ADOBE_GIL_NAMESPACE_END
00315 
00317 //
00318 // std::fill and gil::fill_pixels
00319 //
00321 
00325 
00326 namespace std {
00335     template <typename IL, typename V>
00336     void fill(GIL::pixel_image_iterator<IL> first, GIL::pixel_image_iterator<IL> last, const V& val) {
00337         GIL::gil_function_requires<GIL::MutablePixelLocatorConcept<IL> >();
00338         if (first.is_contiguous()) {
00339             std::fill(first.x(), last.x(), val);
00340         } else {
00341             // fill row by row
00342             std::ptrdiff_t n=last-first;
00343             while (n>0) {
00344                 std::ptrdiff_t numToDo=std::min<const std::ptrdiff_t>(n,(std::ptrdiff_t)(first.width()-first.x_pos()));
00345                 fill_n(first.x(), numToDo, val);
00346                 first+=numToDo;
00347                 n-=numToDo;
00348             }
00349         }
00350     } 
00351 }
00352 
00353 ADOBE_GIL_NAMESPACE_BEGIN
00354 
00357 template <typename V, typename VAL> GIL_FORCEINLINE 
00358 void fill_pixels(const V& img_view, const VAL& val) {
00359     if (img_view.begin().is_contiguous()) {
00360         std::fill(img_view.begin().x(), img_view.end().x(), val);
00361     } else {
00362         for (int y=0; y<img_view.height(); ++y)
00363             std::fill(img_view.row_begin(y),img_view.row_end(y),val);
00364     }   
00365 }
00366 ADOBE_GIL_NAMESPACE_END
00367 
00368 
00369 
00375 
00384 
00385 ADOBE_GIL_NAMESPACE_BEGIN
00386 
00387 
00390 template <typename V, typename F>
00391 F for_each_pixel(const V& img, F fun) {
00392     if (img.begin().is_contiguous()) {
00393         return std::for_each(img.begin().x(), img.end().x(), fun);
00394     } else {
00395         for (int y=0; y<img.height(); ++y)
00396             fun = std::for_each(img.row_begin(y),img.row_end(y),fun);
00397         return fun;
00398     }
00399 }
00400 
00403 template <typename VIEW, typename F>
00404 F for_each_pixel_position(const VIEW& img, F fun) {
00405     typename VIEW::xy_locator loc=img.xy_at(0,0);
00406     for (int y=0; y<img.height(); ++y) {
00407         for (int x=0; x<img.width(); ++x, ++loc.x())
00408             fun(loc);
00409         loc.x()-=img.width(); ++loc.y();
00410     }
00411     return fun;
00412 }
00414 
00415 ADOBE_GIL_NAMESPACE_END
00416 
00422 
00426 
00427 ADOBE_GIL_NAMESPACE_BEGIN
00428 
00429 template <typename I1, typename I2> GIL_FORCEINLINE bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2);
00430 
00431 
00432 namespace detail {
00435     template <typename I1, typename I2>
00436     struct equal_n_fn {
00437         GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, I2 i2) const { return std::equal(i1,i1+n, i2); }
00438     };
00439 
00443     template<typename T, typename CS>
00444     struct equal_n_fn<const pixel<T,CS>*, const pixel<T,CS>*> {
00445         GIL_FORCEINLINE bool operator()(const pixel<T,CS>* i1, std::ptrdiff_t n, const pixel<T,CS>* i2) const { 
00446             return memcmp(i1, i2, n*sizeof(pixel<T,CS>))==0;
00447         }
00448     };
00449     template<typename T, typename CS>
00450     struct equal_n_fn<pixel<T,CS>*, pixel<T,CS>*> : equal_n_fn<const pixel<T,CS>*, const pixel<T,CS>*> {};
00451 
00455     template<typename IC, typename CS>
00456     struct equal_n_fn<planar_ptr<IC,CS>, planar_ptr<IC,CS> > {
00457         GIL_FORCEINLINE bool operator()(const planar_ptr<IC,CS> i1, std::ptrdiff_t n, const planar_ptr<IC,CS> i2) const { 
00458             ptrdiff_t numBytes=n*sizeof(typename std::iterator_traits<IC>::value_type);
00459 
00460             for (int i=0; i<CS::num_channels; ++i)
00461                 if (memcmp(i1.channel_ptr(i), i2.channel_ptr(i), numBytes)!=0)
00462                     return false;
00463             return true;
00464         }
00465     };
00466 
00467 
00468 
00471     template <typename LOC, typename I2>  // IL Models ConstPixelLocatorConcept, O Models PixelIteratorConcept
00472     struct equal_n_fn<GIL::pixel_image_iterator<LOC>,I2> {
00473         GIL_FORCEINLINE bool operator()(GIL::pixel_image_iterator<LOC> i1, std::ptrdiff_t n, I2 i2) const {
00474             GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC> >();
00475             GIL::gil_function_requires<GIL::PixelIteratorConcept<I2> >();
00476             while (n>0) {
00477                 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n, i1.width()-i1.x_pos());
00478                 if (!equal_n(i1.x(), num, i2))
00479                     return false;
00480                 i1+=num;
00481                 i2+=num;
00482                 n-=num;
00483             }
00484             return true;
00485         }
00486     };
00487 
00490     template <typename I1, typename LOC> // I Models PixelIteratorConcept, OL Models PixelLocatorConcept
00491     struct equal_n_fn<I1,GIL::pixel_image_iterator<LOC> > {
00492         GIL_FORCEINLINE bool operator()(I1 i1, std::ptrdiff_t n, GIL::pixel_image_iterator<LOC> i2) const {
00493             GIL::gil_function_requires<GIL::PixelIteratorConcept<I1> >();
00494             GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC> >();
00495             while (n>0) {
00496                 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
00497                 if (!equal_n(i1, num, i2.x()))
00498                     return false;
00499                 i1+=num;
00500                 i2+=num;
00501                 n-=num;
00502             }
00503             return true;
00504         }
00505     };
00506 
00509     template <typename LOC1, typename LOC2>
00510     struct equal_n_fn<GIL::pixel_image_iterator<LOC1>,GIL::pixel_image_iterator<LOC2> > {
00511        GIL_FORCEINLINE bool operator()(GIL::pixel_image_iterator<LOC1> i1, std::ptrdiff_t n, GIL::pixel_image_iterator<LOC2> i2) const {
00512             GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC1> >();
00513             GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC2> >();
00514             if (i1.x_pos()!=i2.x_pos() || i1.width()!=i2.width()) {
00515                 while(n-->0) {
00516                     if (*i1++!=*i2++) return false;
00517                 }
00518             }
00519             while (n>0) {
00520                 std::ptrdiff_t num=std::min<const std::ptrdiff_t>(n,i2.width()-i2.x_pos());
00521                 if (!equal_n(i1.x(), num, i2.x()))
00522                     return false;
00523                 i1+=num;
00524                 i2+=num;
00525                 n-=num;
00526             }
00527             return true;
00528         }
00529     };
00530 }
00531 
00533 template <typename I1, typename I2> GIL_FORCEINLINE
00534 bool equal_n(I1 i1, std::ptrdiff_t n, I2 i2) {
00535     return detail::equal_n_fn<I1,I2>()(i1,n,i2);
00536 }
00537 ADOBE_GIL_NAMESPACE_END
00538 
00539 namespace std {
00551     template <typename LOC1, typename LOC2> GIL_FORCEINLINE 
00552     bool equal(GIL::pixel_image_iterator<LOC1> first, GIL::pixel_image_iterator<LOC1> last, GIL::pixel_image_iterator<LOC2> first2) {
00553         GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC1> >();
00554         GIL::gil_function_requires<GIL::PixelLocatorConcept<LOC2> >();
00555         std::ptrdiff_t n=last-first;
00556         if (first.is_contiguous()) {
00557             if (first2.is_contiguous())
00558                 return GIL::detail::equal_n_fn<typename LOC1::x_iterator,typename LOC2::x_iterator>()(first.x(),n, first2.x());
00559             else
00560                 return GIL::detail::equal_n_fn<typename LOC1::x_iterator,GIL::pixel_image_iterator<LOC2> >()(first.x(),n, first2);
00561         } else {
00562             if (first2.is_contiguous())
00563                 return GIL::detail::equal_n_fn<GIL::pixel_image_iterator<LOC1>,typename LOC2::x_iterator>()(first,n, first2.x());
00564             else
00565                 return GIL::detail::equal_n_fn<GIL::pixel_image_iterator<LOC1>,GIL::pixel_image_iterator<LOC2> >()(first,n,first2);
00566         }
00567     }
00568 }
00569 
00570 ADOBE_GIL_NAMESPACE_BEGIN
00571 
00572 
00573 namespace detail {
00574     struct equal_pixels_fn : public binary_operation_obj<equal_pixels_fn,bool> {
00575         template <typename V1, typename V2>
00576         GIL_FORCEINLINE bool operator()(const V1& v1, const V2& v2) const {
00577             assert(v1.dimensions()==v2.dimensions());
00578             return std::equal(v1.begin(),v1.end(),v2.begin()); // std::equal has overloads with GIL iterators for optimal performance
00579         }
00580     };
00581 }
00582 
00585 template <typename V1, typename V2> GIL_FORCEINLINE 
00586 bool equal_pixels(const V1& v1, const V2& v2) {
00587     return detail::equal_pixels_fn()(v1,v2);
00588 }
00589 ADOBE_GIL_NAMESPACE_END
00590 
00591 
00597 
00601 
00602 ADOBE_GIL_NAMESPACE_BEGIN
00603 
00606 template <typename V1, typename V2, typename F> GIL_FORCEINLINE 
00607 F transform_pixels(const V1& src,const V2& dst, F fun) {
00608     assert(src.dimensions()==dst.dimensions());
00609     for (int y=0; y<src.height(); ++y) {
00610         typename V1::x_iterator srcIt=src.row_begin(y);
00611         typename V2::x_iterator dstIt=dst.row_begin(y);
00612         for (int x=0; x<src.width(); ++x)
00613             dstIt[x]=fun(srcIt[x]);
00614     }
00615     return fun;
00616 }
00617 
00620 template <typename V1, typename V2, typename V3, typename F> GIL_FORCEINLINE 
00621 F transform_pixels(const V1& src1, const V2& src2,const V3& dst, F fun) {
00622     for (int y=0; y<dst.height(); ++y) {
00623         typename V1::x_iterator srcIt1=src1.row_begin(y);
00624         typename V2::x_iterator srcIt2=src2.row_begin(y);
00625         typename V3::x_iterator dstIt=dst.row_begin(y);
00626         for (int x=0; x<dst.width(); ++x)
00627             dstIt[x]=fun(srcIt1[x],srcIt2[x]);
00628     }
00629     return fun;
00630 }
00631 
00634 template <typename V1, typename V2, typename F> GIL_FORCEINLINE 
00635 F transform_pixel_positions(const V1& src,const V2& dst, F fun) {
00636     assert(src.dimensions()==dst.dimensions());
00637     typename V1::xy_locator loc=src.xy_at(0,0);
00638     for (int y=0; y<src.height(); ++y) {
00639         typename V2::x_iterator dstIt=dst.row_begin(y);
00640         for (int x=0; x<src.width(); ++x, ++loc.x())
00641             dstIt[x]=fun(loc);
00642         loc.x()-=src.width(); ++loc.y();
00643     }
00644     return fun;
00645 }
00646 
00649 template <typename V1, typename V2, typename V3, typename F> GIL_FORCEINLINE 
00650 F transform_pixel_positions(const V1& src1,const V2& src2,const V3& dst, F fun) {
00651     assert(src1.dimensions()==dst.dimensions());
00652     assert(src2.dimensions()==dst.dimensions());
00653     typename V1::xy_locator loc1=src1.xy_at(0,0);
00654     typename V2::xy_locator loc2=src2.xy_at(0,0);
00655     for (int y=0; y<src1.height(); ++y) {
00656         typename V3::x_iterator dstIt=dst.row_begin(y);
00657         for (int x=0; x<src1.width(); ++x, ++loc1.x(), ++loc2.x())
00658             dstIt[x]=fun(loc1,loc2);
00659         loc1.x()-=src1.width(); ++loc1.y();
00660         loc2.x()-=src2.width(); ++loc2.y();
00661     }
00662     return fun;
00663 }
00665 
00666 
00667 
00668 ADOBE_GIL_NAMESPACE_END
00669 
00670 #endif

Copyright © 2006 Adobe Systems Incorporated.

Use of this website signifies your agreement to the Terms of Use and Online Privacy Policy.

Search powered by Google