text: /* -*-c++-*- */
  /* osgEarth - Dynamic map generation toolkit for OpenSceneGraph
   * Copyright 2020 Pelican Mapping
   * http://osgearth.org
   *
   * osgEarth is free software; you can redistribute it and/or modify
   * it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
   *
   * You should have received a copy of the GNU Lesser General Public License
   * along with this program.  If not, see <http://www.gnu.org/licenses/>
   */
  #ifndef OSGEARTH_FEATURES_FEATURE_IMAGE_LAYER
  #define OSGEARTH_FEATURES_FEATURE_IMAGE_LAYER 1
  
  #include <osgEarth/ImageLayer>
  #include <osgEarth/LayerReference>
  #include <osgEarth/FeatureSource>
  #include <osgEarth/StyleSheet>
  
  namespace osgEarth
  {
      namespace Util
      {
          class OSGEARTH_EXPORT FeatureImageRenderer
          {
          public:
              bool render(
                  const TileKey& key,
                  Session* session,
                  const StyleSheet* styles,
                  osg::Image* target,
                  ProgressCallback* progress) const;
  
          protected:
              virtual bool renderFeaturesForStyle(
                  Session*           session,
                  const Style&       style,
                  const FeatureList& features,
                  const GeoExtent&   imageExtent,
                  osg::Image*        out_image ) const = 0;
  
              osg::ref_ptr<FeatureFilterChain> _filterChain;
  
          private:
              bool queryAndRenderFeaturesForStyle(
                  Session*          session,
                  const Style&      style,
                  const Query&      query,
                  const GeoExtent&  imageExtent,
                  osg::Image*       out_image,
                  ProgressCallback* progress) const;
          
              void getFeatures(
                  Session* session,
                  const Query& query, 
                  const GeoExtent& imageExtent, 
                  FeatureList& features,
                  ProgressCallback* progress) const;
          };
      }
  
      /**
       * Rasterizes feature data into an image layer.
       */
      class OSGEARTH_EXPORT FeatureImageLayer : public osgEarth::ImageLayer,
                                                public osgEarth::Util::FeatureImageRenderer
      {
      public: // serialization
          class OSGEARTH_EXPORT Options : public ImageLayer::Options {
          public:
              META_LayerOptions(osgEarth, Options, ImageLayer::Options);
              OE_OPTION_LAYER(FeatureSource, featureSource);
              OE_OPTION_VECTOR(ConfigOptions, filters);
              OE_OPTION_LAYER(StyleSheet, styleSheet);
              OE_OPTION(double, gamma);
              virtual Config getConfig() const;
          private:
              void fromConfig( const Config& conf );
          };
  
      public:
          META_Layer(osgEarth, FeatureImageLayer, Options, osgEarth::ImageLayer, FeatureImage);
  
  
          //! Sets the feature source to get road data from; call either this
          //! or setFeatureSourceLayer
          void setFeatureSource(FeatureSource* source);
          inline FeatureSource* getFeatureSource() const;
  
          //! Style sheet to use to render feature data
          void setStyleSheet(StyleSheet* styles);
          inline StyleSheet* getStyleSheet() const;
  
      public: // FeatureImageRenderer
  
          virtual bool renderFeaturesForStyle(
              Session*           session,
              const Style&       style,
              const FeatureList& features,
              const GeoExtent&   imageExtent,
              osg::Image*        out_image ) const;
  
      public: // ImageLayer
  
          // Opens the layer and returns a status
          virtual Status openImplementation();
  
          virtual GeoImage createImageImplementation(const TileKey& key, ProgressCallback* progress) const;
  
      protected: // Layer
  
          // Called by Map when it adds this layer
          virtual void addedToMap(const class Map*);
  
          // Called by Map when it removes this layer
          virtual void removedFromMap(const class Map*);
  
          // post-ctor initialization
          virtual void init();
  
      protected:
  
          virtual ~FeatureImageLayer() { }
  
      private:
          osg::ref_ptr<Session> _session;
          osg::ref_ptr<const FeatureProfile> _featureProfile;
          optional<double> _gamma;
  
          void updateSession();
  
          bool renderFeaturesForStyle(
              Session*           session,
              const Style&       style,
              const FeatureList& features,
              osg::Referenced*   buildData,
              const GeoExtent&   imageExtent,
              osg::Image*        image ) const;
  
          osg::Image* allocateImage() const;
  
          bool preProcess(osg::Image* image) const;
  
          bool postProcess(osg::Image* image) const;
      };
  
      // template/inline impls .................................................
  
      FeatureSource* FeatureImageLayer::getFeatureSource() const { return options().featureSource().getLayer(); }
      StyleSheet* FeatureImageLayer::getStyleSheet() const { return options().styleSheet().getLayer(); }
  } // namespace osgEarth
  
  OSGEARTH_SPECIALIZE_CONFIG(osgEarth::FeatureImageLayer::Options);
  
  #endif // OSGEARTH_FEATURES_FEATURE_IMAGE_LAYER
  