TuttleOFX  1
utilgil.hpp
Go to the documentation of this file.
00001 #ifndef _TERRY_FREETYPE_UTIL_HPP_
00002 #define _TERRY_FREETYPE_UTIL_HPP_
00003 
00004 // (C) Copyright Tom Brinkman 2007.
00005 // Distributed under the Boost Software License, Version 1.0. (See accompanying
00006 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
00007 
00008 #include <boost/gil/image.hpp>
00009 #include <terry/numeric/operations.hpp>
00010 #include <terry/numeric/assign.hpp>
00011 #include <terry/numeric/operations_assign.hpp>
00012 
00013 namespace terry {
00014 
00015 enum
00016 {
00017         Left    = ( 0x1 << 0 ),
00018         Center  = ( 0x1 << 1 ),
00019         Right   = ( 0x1 << 2 ),
00020         Top     = ( 0x1 << 3 ),
00021         Middle  = ( 0x1 << 4 ),
00022         Bottom  = ( 0x1 << 5 ),
00023         FMiddle = ( 0x1 << 6 ),
00024         FBottom = ( 0x1 << 7 ),
00025 };
00026 
00027 struct make_special_interval
00028 {
00029         int size, r, adj, pos;
00030 
00031         make_special_interval( int width, int size )
00032                 : size( size )
00033                 , r( ( width - 1 ) % size )
00034                 , adj( ( width - 1 ) / size )
00035                 , pos( 0 ) {}
00036 
00037         int operator()( int in )
00038         {
00039                 int out = pos;
00040 
00041                 pos += adj;
00042 
00043                 if( r )
00044                 {
00045                         ++pos;
00046                         --r;
00047                 }
00048 
00049                 return out;
00050         }
00051 
00052 };
00053 
00054 struct make_alpha_blend
00055 {
00056         double alpha;
00057 
00058         make_alpha_blend( double alpha ) : alpha( alpha ) {}
00059 
00060         template <typename T>
00061         void operator()( T& dst, const T src )
00062         {
00063                 double dbl = ( dst * alpha - src * alpha + src * 255.0 ) / 255.0;
00064 
00065                 dst = (int) dbl;
00066         }
00067 
00068 };
00069 
00070 template<typename GlyphView, typename View>
00071 inline
00072 void copy_and_convert_alpha_blended_pixels( const GlyphView& glyphView, const typename View::value_type& glyphColor, const View& dstView )
00073 {
00074         using namespace boost::gil;
00075         //      typedef typename GlyphView::value_type GlyphPixel;
00076         typedef typename View::value_type Pixel;
00077 
00078         //      typedef pixel<bits32f, layout<typename color_space_type<GlyphView>::type> > GlyphPixel32f;
00079         //      typedef pixel<typename channel_type<view_t>::type, layout<gray_t> > PixelGray;
00080 
00081         //      BOOST_STATIC_ASSERT(( boost::is_same<typename color_space_type<glyphView>::type, gray_t>::value ));
00082         //      BOOST_STATIC_ASSERT(( boost::is_same<typename channel_type<glyphView>::type, bits32f>::value ));
00083 
00084         for( int y = 0;
00085              y < dstView.height();
00086              ++y )
00087         {
00088                 typename GlyphView::x_iterator it_glyph = glyphView.x_at( 0, y );
00089                 typename View::x_iterator it_img        = dstView.x_at( 0, y );
00090                 for( int x = 0;
00091                      x < dstView.width();
00092                      ++x, ++it_glyph, ++it_img )
00093                 {
00094                         Pixel pColor = glyphColor;
00095                         numeric::pixel_multiplies_scalar_assign_t<float, Pixel>()
00096                         (
00097                             get_color( *it_glyph, gray_color_t() ),
00098                             pColor
00099                         );
00100                         numeric::pixel_multiplies_scalar_assign_t<float, Pixel>()
00101                         (
00102                             channel_invert( get_color( *it_glyph, gray_color_t() ) ),
00103                             *it_img
00104                         );
00105                         numeric::pixel_plus_assign_t<Pixel, Pixel>()
00106                         (
00107                             pColor,
00108                             *it_img
00109                         );
00110 //                      TUTTLE_CLOG_VAR( TUTTLE_TRACE, get_color( *it_glyph, gray_color_t() ) );
00111 //                      TUTTLE_CLOG_VAR( TUTTLE_TRACE, (*it_img)[0] );
00112 //                      TUTTLE_CLOG_VAR( TUTTLE_TRACE, (int)(color[0]) );
00113 //                      TUTTLE_CLOG_VAR( TUTTLE_TRACE, (int)(pColor[0]) );
00114                 }
00115         }
00116 }
00117 
00118 template <typename view_t, typename value_type>
00119 inline void wuline( const view_t& view, const value_type& pixel,
00120                     int X0, int Y0, int X1, int Y1,
00121                     int NumLevels, int IntensityBits )
00122 {
00123         unsigned short IntensityShift, ErrorAdj, ErrorAcc;
00124         unsigned short ErrorAccTemp, Weighting, WeightingComplementMask;
00125         short DeltaX, DeltaY, Temp, XDir;
00126 
00127         if( Y0 > Y1 )
00128         {
00129                 Temp = Y0;
00130                 Y0   = Y1;
00131                 Y1   = Temp;
00132                 Temp = X0;
00133                 X0   = X1;
00134                 X1   = Temp;
00135         }
00136 
00137         view( X0, Y0 ) = pixel;
00138 
00139         if( ( DeltaX = X1 - X0 ) >= 0 )
00140         {
00141                 XDir = 1;
00142         }
00143         else
00144         {
00145                 XDir   = -1;
00146                 DeltaX = -DeltaX;
00147         }
00148 
00149         if( ( DeltaY = Y1 - Y0 ) == 0 )
00150         {
00151                 while( DeltaX-- != 0 )
00152                 {
00153                         X0            += XDir;
00154                         view( X0, Y0 ) = pixel;
00155                 }
00156 
00157                 return;
00158         }
00159 
00160         if( DeltaX == 0 )
00161         {
00162                 do
00163                 {
00164                         Y0++;
00165                         view( X0, Y0 ) = pixel;
00166                 }
00167                 while( --DeltaY != 0 );
00168 
00169                 return;
00170         }
00171 
00172         if( DeltaX == DeltaY )
00173         {
00174                 do
00175                 {
00176                         X0 += XDir;
00177                         Y0++;
00178                         view( X0, Y0 ) = pixel;
00179                 }
00180                 while( --DeltaY != 0 );
00181 
00182                 return;
00183         }
00184 
00185         ErrorAcc                = 0;
00186         IntensityShift          = 16 - IntensityBits;
00187         WeightingComplementMask = NumLevels - 1;
00188 
00189         if( DeltaY > DeltaX )
00190         {
00191                 ErrorAdj = ( (unsigned long) DeltaX << 16 ) / (unsigned long) DeltaY;
00192 
00193                 while( --DeltaY )
00194                 {
00195                         ErrorAccTemp = ErrorAcc;
00196                         ErrorAcc    += ErrorAdj;
00197 
00198                         if( ErrorAcc <= ErrorAccTemp )
00199                                 X0 += XDir;
00200 
00201                         Y0++;
00202 
00203                         Weighting = ErrorAcc >> IntensityShift;
00204 
00205                         value_type dst = pixel;
00206                         boost::gil::static_for_each( dst, view( X0, Y0 ),
00207                                                      make_alpha_blend( ( Weighting ^ WeightingComplementMask ) ) );
00208                         view( X0, Y0 ) = dst;
00209 
00210                         dst = pixel;
00211                         boost::gil::static_for_each( dst, view( X0 + XDir, Y0 ),
00212                                                      make_alpha_blend( Weighting ) );
00213                         view( X0 + XDir, Y0 ) = dst;
00214                 }
00215 
00216                 view( X1, Y1 ) = pixel;
00217                 return;
00218         }
00219 
00220         ErrorAdj = ( (unsigned long) DeltaY << 16 ) / (unsigned long) DeltaX;
00221         while( --DeltaX )
00222         {
00223                 ErrorAccTemp = ErrorAcc;
00224                 ErrorAcc    += ErrorAdj;
00225 
00226                 if( ErrorAcc <= ErrorAccTemp )
00227                         Y0++;
00228 
00229                 X0 += XDir;
00230 
00231                 Weighting = ErrorAcc >> IntensityShift;
00232 
00233                 value_type dst = pixel;
00234                 boost::gil::static_for_each( dst, view( X0, Y0 ),
00235                                              make_alpha_blend( Weighting ^ WeightingComplementMask ) );
00236                 view( X0, Y0 ) = dst;
00237 
00238                 dst = pixel;
00239                 boost::gil::static_for_each( dst, view( X0, Y0 + 1 ),
00240                                              make_alpha_blend( Weighting ) );
00241                 view( X0, Y0 + 1 ) = dst;
00242         }
00243 
00244         view( X1, Y1 ) = pixel;
00245 }
00246 
00247 template <typename view_t>
00248 struct draw_line
00249 {
00250         typedef typename view_t::value_type value_type;
00251         const view_t& view;
00252         const value_type& pixel;
00253         short NumLevels;
00254         unsigned short IntensityBits;
00255 
00256         draw_line( const view_t& view, const value_type& pixel,
00257                    int NumLevels = 256, int IntensityBits = 8 )
00258                 : view( view )
00259                 , pixel( pixel )
00260                 , NumLevels( NumLevels )
00261                 , IntensityBits( IntensityBits ) {}
00262 
00263         template <typename point_t>
00264         void operator()( point_t pt0, point_t pt1 )
00265         {
00266                 wuline( view, pixel,
00267                         pt0.x, pt0.y, pt1.x, pt1.y,
00268                         NumLevels, IntensityBits );
00269         }
00270 
00271 };
00272 
00273 }
00274 
00275 #endif
00276