root/src/servers/app/drawing/Painter/drawing_modes/PixelFormat.h
/*
 * Copyright 2005, Stephan Aßmus <superstippi@gmx.de>.
 * Copyright 2008, Andrej Spielmann <andrej.spielmann@seh.ox.ac.uk>
 * All rights reserved. Distributed under the terms of the MIT License.
 *
 * Copyright 2002-2004 Maxim Shemanarev (http://www.antigrain.com)
 *
 * A class implementing the AGG "pixel format" interface which maintains
 * a PatternHandler and pointers to blending functions implementing the
 * different BeOS "drawing_modes".
 *
 */

#ifndef PIXEL_FORMAT_H
#define PIXEL_FORMAT_H

#include <agg_basics.h>
#include <agg_color_rgba.h>
#include <agg_rendering_buffer.h>
#include <agg_pixfmt_rgba.h>

#include <GraphicsDefs.h>

#include "AggCompOpAdapter.h"

class PatternHandler;

class PixelFormat {
 public:
        typedef agg::rgba8                                              color_type;
        typedef agg::rendering_buffer                   agg_buffer;
        typedef agg::rendering_buffer::row_data row_data;
        typedef agg::order_bgra                                 order_type;

        typedef agg::comp_op_rgba_src_in<color_type, order_type>        comp_src_in;
        typedef agg::comp_op_rgba_src_out<color_type, order_type>       comp_src_out;
        typedef agg::comp_op_rgba_src_atop<color_type, order_type>      comp_src_atop;
        typedef agg::comp_op_rgba_dst_over<color_type, order_type>      comp_dst_over;
        typedef agg::comp_op_rgba_dst_in<color_type, order_type>        comp_dst_in;
        typedef agg::comp_op_rgba_dst_out<color_type, order_type>       comp_dst_out;
        typedef agg::comp_op_rgba_dst_atop<color_type, order_type>      comp_dst_atop;
        typedef agg::comp_op_rgba_xor<color_type, order_type>           comp_xor;
        typedef agg::comp_op_rgba_clear<color_type, order_type>         comp_clear;
        typedef agg::comp_op_rgba_difference<color_type, order_type>
                comp_difference;
        typedef agg::comp_op_rgba_lighten<color_type, order_type>       comp_lighten;
        typedef agg::comp_op_rgba_darken<color_type, order_type>        comp_darken;

        typedef AggCompOpAdapter<comp_src_in, agg_buffer>               alpha_src_in;
        typedef AggCompOpAdapter<comp_src_out, agg_buffer>              alpha_src_out;
        typedef AggCompOpAdapter<comp_src_atop, agg_buffer>             alpha_src_atop;
        typedef AggCompOpAdapter<comp_dst_over, agg_buffer>             alpha_dst_over;
        typedef AggCompOpAdapter<comp_dst_in, agg_buffer>               alpha_dst_in;
        typedef AggCompOpAdapter<comp_dst_out, agg_buffer>              alpha_dst_out;
        typedef AggCompOpAdapter<comp_dst_atop, agg_buffer>             alpha_dst_atop;
        typedef AggCompOpAdapter<comp_xor, agg_buffer>                  alpha_xor;
        typedef AggCompOpAdapter<comp_clear, agg_buffer>                alpha_clear;
        typedef AggCompOpAdapter<comp_difference, agg_buffer>   alpha_difference;
        typedef AggCompOpAdapter<comp_lighten, agg_buffer>              alpha_lighten;
        typedef AggCompOpAdapter<comp_darken, agg_buffer>               alpha_darken;

        enum base_scale_e
        {
                base_shift = color_type::base_shift,
                base_scale = color_type::base_scale,
                base_mask  = color_type::base_mask,
                pix_width  = 4,
        };

        typedef void (*blend_pixel_f)(int x, int y, const color_type& c,
                                                                  uint8 cover,
                                                                  agg_buffer* buffer,
                                                                  const PatternHandler* pattern);

        typedef void (*blend_line)(int x, int y, unsigned len,
                                                           const color_type& c, uint8 cover,
                                                           agg_buffer* buffer,
                                                           const PatternHandler* pattern);

        typedef void (*blend_solid_span)(int x, int y, unsigned len,
                                                                         const color_type& c,
                                                                         const uint8* covers,
                                                                         agg_buffer* buffer,
                                                                         const PatternHandler* pattern);

        typedef void (*blend_color_span)(int x, int y, unsigned len,
                                                                         const color_type* colors,
                                                                         const uint8* covers,
                                                                         uint8 cover,
                                                                         agg_buffer* buffer,
                                                                         const PatternHandler* pattern);

                        // PixelFormat class
                                                                PixelFormat(agg::rendering_buffer& buffer,
                                                                                        const PatternHandler* handler);

                                                                ~PixelFormat();


                        void                            SetDrawingMode(drawing_mode mode,
                                                                                           source_alpha alphaSrcMode,
                                                                                           alpha_function alphaFncMode);

                        // AGG "pixel format" interface
        inline  unsigned                        width() const
                                                                        { return fBuffer->width(); }
        inline  unsigned                        height() const
                                                                        { return fBuffer->height(); }
        inline  int                                     stride() const
                                                                        { return fBuffer->stride(); }

        inline  uint8*                          row_ptr(int y)
                                                                        { return fBuffer->row_ptr(y); }
        inline  const uint8*            row_ptr(int y) const
                                                                        { return fBuffer->row_ptr(y); }
        inline  row_data                        row(int y) const
                                                                        { return fBuffer->row(y); }

        inline  uint8*                          pix_ptr(int x, int y);
        inline  const uint8*            pix_ptr(int x, int y) const;

        inline  static  void            make_pix(uint8* p, const color_type& c);
//      inline  color_type                      pixel(int x, int y) const;

        inline  void                            blend_pixel(int x, int y,
                                                                                        const color_type& c,
                                                                                        uint8 cover);


        inline  void                            blend_hline(int x, int y,
                                                                                        unsigned len,
                                                                                        const color_type& c,
                                                                                        uint8 cover);

        inline  void                            blend_vline(int x, int y,
                                                                                        unsigned len,
                                                                                        const color_type& c,
                                                                                        uint8 cover);

        inline  void                            blend_solid_hspan(int x, int y,
                                                                                                  unsigned len,
                                                                                                  const color_type& c,
                                                                                                  const uint8* covers);

        inline  void                            blend_solid_hspan_subpix(int x, int y,
                                                                                                  unsigned len,
                                                                                                  const color_type& c,
                                                                                                  const uint8* covers);

        inline  void                            blend_solid_vspan(int x, int y,
                                                                                                  unsigned len,
                                                                                                  const color_type& c,
                                                                                                  const uint8* covers);

        inline  void                            blend_color_hspan(int x, int y,
                                                                                                  unsigned len,
                                                                                                  const color_type* colors,
                                                                                                  const uint8* covers,
                                                                                                  uint8 cover);

        inline  void                            blend_color_vspan(int x, int y,
                                                                                                  unsigned len,
                                                                                                  const color_type* colors,
                                                                                                  const uint8* covers,
                                                                                                  uint8 cover);

 private:
        agg::rendering_buffer*          fBuffer;
        const PatternHandler*           fPatternHandler;

        blend_pixel_f                           fBlendPixel;
        blend_line                                      fBlendHLine;
        blend_line                                      fBlendVLine;
        blend_solid_span                        fBlendSolidHSpan;
        blend_solid_span            fBlendSolidHSpanSubpix;
        blend_solid_span                        fBlendSolidVSpan;
        blend_color_span                        fBlendColorHSpan;
        blend_color_span                        fBlendColorVSpan;

        template<typename T>
        void SetAggCompOpAdapter()
        {
                fBlendPixel = T::blend_pixel;
                fBlendHLine = T::blend_hline;
                fBlendSolidHSpanSubpix = T::blend_solid_hspan_subpix;
                fBlendSolidHSpan = T::blend_solid_hspan;
                fBlendSolidVSpan = T::blend_solid_vspan;
                fBlendColorHSpan = T::blend_color_hspan;
        }
};

// inlined functions

// pix_ptr
inline uint8*
PixelFormat::pix_ptr(int x, int y)
{
        return fBuffer->row_ptr(y) + x * pix_width;
}

// pix_ptr
inline const uint8*
PixelFormat::pix_ptr(int x, int y) const
{
        return fBuffer->row_ptr(y) + x * pix_width;
}

// make_pix
inline void
PixelFormat::make_pix(uint8* p, const color_type& c)
{
        p[0] = c.b;
        p[1] = c.g;
        p[2] = c.r;
        p[3] = c.a;
}

//// pixel
//inline color_type
//PixelFormat::pixel(int x, int y) const
//{
//      const uint8* p = (const uint8*)fBuffer->row_ptr(y);
//      if (p) {
//              p += x << 2;
//              return color_type(p[2], p[1], p[0], p[3]);
//      }
//      return color_type::no_color();
//}

// blend_pixel
inline void
PixelFormat::blend_pixel(int x, int y, const color_type& c, uint8 cover)
{
        fBlendPixel(x, y, c, cover, fBuffer, fPatternHandler);
}

// blend_hline
inline void
PixelFormat::blend_hline(int x, int y, unsigned len,
                                                 const color_type& c, uint8 cover)
{
        fBlendHLine(x, y, len, c, cover, fBuffer, fPatternHandler);
}

// blend_vline
inline void
PixelFormat::blend_vline(int x, int y, unsigned len,
                                                 const color_type& c, uint8 cover)
{
        fBlendVLine(x, y, len, c, cover, fBuffer, fPatternHandler);
}

// blend_solid_hspan
inline void
PixelFormat::blend_solid_hspan(int x, int y, unsigned len,
                                                           const color_type& c, const uint8* covers)
{
        fBlendSolidHSpan(x, y, len, c, covers, fBuffer, fPatternHandler);
}

// blend_solid_hspan_subpix
inline void
PixelFormat::blend_solid_hspan_subpix(int x, int y, unsigned len,
                                                           const color_type& c, const uint8* covers)
{
        fBlendSolidHSpanSubpix(x, y, len, c, covers, fBuffer, fPatternHandler);
}

// blend_solid_vspan
inline void
PixelFormat::blend_solid_vspan(int x, int y, unsigned len,
                                                           const color_type& c, const uint8* covers)
{
        fBlendSolidVSpan(x, y, len, c, covers, fBuffer, fPatternHandler);
}

// blend_color_hspan
inline void
PixelFormat::blend_color_hspan(int x, int y, unsigned len,
                                                           const color_type* colors,
                                                           const uint8* covers,
                                                           uint8 cover)
{
        fBlendColorHSpan(x, y, len, colors, covers, cover,
                                         fBuffer, fPatternHandler);
}

// blend_color_vspan
inline void
PixelFormat::blend_color_vspan(int x, int y, unsigned len,
                                                           const color_type* colors,
                                                           const uint8* covers,
                                                           uint8 cover)
{
        fBlendColorVSpan(x, y, len, colors, covers, cover,
                                         fBuffer, fPatternHandler);
}

#endif // PIXEL_FORMAT_H