<commit_before>/* This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * Mapnik is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id$

#include <QtGui>

#include <boost/bind.hpp>

#include <mapnik/agg_renderer.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/memory_datasource.hpp>
#include <mapnik/feature_kv_iterator.hpp>
#include "mapwidget.hpp"
#include "info_dialog.hpp"

using mapnik::image_32;
using mapnik::Map;
using mapnik::layer;
using mapnik::box2d;
using mapnik::coord2d;
using mapnik::feature_ptr;
using mapnik::geometry_ptr;
using mapnik::CoordTransform;
using mapnik::projection;
using mapnik::scale_denominator;
using mapnik::feature_kv_iterator;

double scales [] = {279541132.014,
                    139770566.007,
                    69885283.0036,
                    34942641.5018,
                    17471320.7509,
                    8735660.37545,
                    4367830.18772,
                    2183915.09386,
                    1091957.54693,
                    545978.773466,
                    272989.386733,
                    136494.693366,
                    68247.3466832,
                    34123.6733416,
                    17061.8366708,
                    8530.9183354,
                    4265.4591677,
                    2132.72958385,
                    1066.36479192,
                    533.182395962};

MapWidget::MapWidget(QWidget *parent)
   : QWidget(parent),
     map_(),
     selected_(1),
     extent_(),
     cur_tool_(ZoomToBox),
     start_x_(0),
     start_y_(0),
     end_x_(0),
     end_y_(0),
     drag_(false),
     first_(true),
     pen_(QColor(0,0,255,96)),
     selectedLayer_(-1),
     scaling_factor_(1.0)
{
   pen_.setWidth(3);
   pen_.setCapStyle(Qt::RoundCap);
   pen_.setJoinStyle(Qt::RoundJoin);
}

void MapWidget::setTool(eTool tool)
{
   cur_tool_=tool;
}

void MapWidget::paintEvent(QPaintEvent*)
{
   QPainter painter(this);

   if (drag_)
   {
      if (cur_tool_ == ZoomToBox)
      {
         unsigned width = end_x_-start_x_;
         unsigned height = end_y_-start_y_;
         painter.drawPixmap(QPoint(0, 0),pix_);
         painter.setPen(pen_);
         painter.setBrush(QColor(200,200,255,128));
         painter.drawRect(start_x_,start_y_,width,height);
      }
      else if (cur_tool_ == Pan)
      {
         int dx = end_x_-start_x_;
         int dy = end_y_-start_y_;
         painter.setBrush(QColor(200,200,200,128));
         painter.drawRect(0,0,width(),height());
         painter.drawPixmap(QPoint(dx,dy),pix_);
      }
   }
   else
   {
      painter.drawPixmap(QPoint(0, 0),pix_);
   }
   painter.end();
}

void MapWidget::resizeEvent(QResizeEvent * ev)
{
   if (map_)
   {
      map_->resize(ev->size().width(),ev->size().height());
      updateMap();
   }
}

void MapWidget::mousePressEvent(QMouseEvent* e)
{
   if (e->button()==Qt::LeftButton)
   {
      if (cur_tool_ == ZoomToBox || cur_tool_==Pan)
      {
         start_x_ = e->x();
         start_y_ = e->y();
         drag_=true;
      }
      else if (cur_tool_==Info)
      {
         if (map_)
         {
            QVector<QPair<QString,QString> > info;

            projection map_proj(map_->srs()); // map projection
            double scale_denom = scale_denominator(*map_,map_proj.is_geographic());
            CoordTransform t(map_->width(),map_->height(),map_->get_current_extent());

            for (unsigned index = 0; index <  map_->layer_count();++index)
            {
               if (int(index) != selectedLayer_) continue;

               layer & layer = map_->layers()[index];
               if (!layer.visible(scale_denom)) continue;
               std::string name = layer.name();
               double x = e->x();
               double y = e->y();
               std::cout << "query at " << x << "," << y << "\n";
               projection layer_proj(layer.srs());
               mapnik::proj_transform prj_trans(map_proj,layer_proj);
               //std::auto_ptr<mapnik::memory_datasource> data(new mapnik::memory_datasource);
               mapnik::featureset_ptr fs = map_->query_map_point(index,x,y);

               if (fs)
               {
                  feature_ptr feat  = fs->next();
                  if (feat)
                  {

                      feature_kv_iterator itr(*feat,true);
                      feature_kv_iterator end(*feat);

                      for ( ;itr!=end; ++itr)
                      {
                          info.push_back(QPair<QString,QString>(QString(boost::get<0>(*itr).c_str()),
                                                                boost::get<1>(*itr).to_string().c_str()));
                      }

                      typedef mapnik::coord_transform2<mapnik::CoordTransform,mapnik::geometry_type> path_type;

                     for  (unsigned i=0; i<feat->num_geometries();++i)
                     {
                        mapnik::geometry_type & geom = feat->get_geometry(i);
                        path_type path(t,geom,prj_trans);
                        if (geom.num_points() > 0)
                        {
                           QPainterPath qpath;
                           double x,y;
                           path.vertex(&x,&y);
                           qpath.moveTo(x,y);
                           for (unsigned j = 1; j < geom.num_points(); ++j)
                           {
                              path.vertex(&x,&y);
                              qpath.lineTo(x,y);
                           }
                           QPainter painter(&pix_);
                           QPen pen(QColor(255,0,0,96));
                           pen.setWidth(3);
                           pen.setCapStyle(Qt::RoundCap);
                           pen.setJoinStyle(Qt::RoundJoin);
                           painter.setPen(pen);
                           painter.drawPath(qpath);
                           update();
                        }
                     }
                  }
               }

               if (info.size() > 0)
               {
                  info_dialog info_dlg(info,this);
                  info_dlg.exec();
                  break;
               }
            }

            // remove annotation layer
            map_->layers().erase(remove_if(map_->layers().begin(),
                                           map_->layers().end(),
                                           bind(&layer::name,_1) == "*annotations*")
                                 , map_->layers().end());
         }
      }
   }
   else if (e->button()==Qt::RightButton)
   {
      //updateMap();
   }
}

void MapWidget::mouseMoveEvent(QMouseEvent* e)
{
   if (cur_tool_ == ZoomToBox || cur_tool_==Pan)
   {
      end_x_ = e->x();
      end_y_ = e->y();
      update();
   }
}

void MapWidget::mouseReleaseEvent(QMouseEvent* e)
{
   if (e->button()==Qt::LeftButton)
   {
      end_x_ = e->x();
      end_y_ = e->y();
      if (cur_tool_ == ZoomToBox)
      {
         drag_=false;
         if (map_)
         {
            CoordTransform t(map_->width(),map_->height(),map_->get_current_extent());
            box2d<double> box = t.backward(box2d<double>(start_x_,start_y_,end_x_,end_y_));
            map_->zoom_to_box(box);
            updateMap();
         }
      }
      else if (cur_tool_==Pan)
      {
         drag_=false;
         if (map_)
         {
            int cx = int(0.5 * map_->width());
            int cy = int(0.5 * map_->height());
            int dx = end_x_ - start_x_;
            int dy = end_y_ - start_y_;
            map_->pan(cx - dx ,cy - dy);
            updateMap();
         }
      }
   }
}

void MapWidget::keyPressEvent(QKeyEvent *e)
{
   std::cout << "key pressed:"<< e->key()<<"\n";
   switch (e->key()) {
      case Qt::Key_Minus:
         zoomOut();
         break;
      case Qt::Key_Plus:
      case 61:
         zoomIn();
         break;
      case 65:
         defaultView();
         break;
      case Qt::Key_Up:
         panUp();
         break;
      case Qt::Key_Down:
         panDown();
         break;
      case Qt::Key_Left:
         panLeft();
         break;
      case Qt::Key_Right:
         panRight();
         break;
      case 49:
         zoomToLevel(10);
         break;
      case 50:
         zoomToLevel(11);
         break;
      case 51:
         zoomToLevel(12);
         break;
      case 52:
         zoomToLevel(13);
         break;
      case 53:
         zoomToLevel(14);
         break;
      case 54:
         zoomToLevel(15);
         break;
      case 55:
         zoomToLevel(16);
         break;
      case 56:
         zoomToLevel(17);
         break;
      case 57:
         zoomToLevel(18);
         break;
   default:
       QWidget::keyPressEvent(e);
   }

}

void MapWidget::zoomToBox(mapnik::box2d<double> const& bbox)
{
   if (map_)
   {
      map_->zoom_to_box(bbox);
      updateMap();
   }
}

void MapWidget::defaultView()
{
   if (map_)
   {
      map_->resize(width(),height());
      map_->zoom_all();
      updateMap();
   }
}

void MapWidget::zoomIn()
{
   if (map_)
   {
      map_->zoom(0.5);
      updateMap();
   }
}

void MapWidget::zoomOut()
{
   if (map_)
   {
      map_->zoom(2.0);
      updateMap();
   }
}

void MapWidget::panUp()
{
   if (map_)
   {
      double cx = 0.5*map_->width();
      double cy = 0.5*map_->height();
      map_->pan(int(cx),int(cy - cy*0.25));
      updateMap();
   }
}

void MapWidget::panDown()
{
   if (map_)
   {
      double cx = 0.5*map_->width();
      double cy = 0.5*map_->height();
      map_->pan(int(cx),int(cy + cy*0.25));
      updateMap();
   }
}

void MapWidget::panLeft()
{
   if (map_)
   {
      double cx = 0.5*map_->width();
      double cy = 0.5*map_->height();
      map_->pan(int(cx - cx * 0.25),int(cy));
      updateMap();
   }
}

void MapWidget::panRight()
{
   if (map_)
   {
      double cx = 0.5*map_->width();
      double cy = 0.5*map_->height();
      map_->pan(int(cx + cx * 0.25),int(cy));
      updateMap();
   }
}

void MapWidget::zoomToLevel(int level)
{
   if ( map_ && level >= 0 && level < 19 )
   {
      double scale_denom  = scales[level];
      std::cerr << "scale denominator = " << scale_denom << "\n";
      mapnik::box2d<double> ext = map_->get_current_extent();
      double width = static_cast<double>(map_->width());
      double height= static_cast<double>(map_->height());
      mapnik::coord2d pt = ext.center();

      double res = scale_denom * 0.00028;

      mapnik::box2d<double> box(pt.x - 0.5 * width * res,
                                   pt.y - 0.5 * height*res,
                                   pt.x + 0.5 * width * res,
                                   pt.y + 0.5 * height*res);
      map_->zoom_to_box(box);
      updateMap();
   }
}

void MapWidget::export_to_file(unsigned ,unsigned ,std::string const&,std::string const&)
{
   //image_32 image(width,height);
   //agg_renderer renderer(map,image);
   //renderer.apply();
   //image.saveToFile(filename,type);
}

void MapWidget::set_scaling_factor(double scaling_factor)
{
    scaling_factor_ = scaling_factor;
}

void MapWidget::updateMap()
{
   if (map_)
   {
      unsigned width=map_->width();
      unsigned height=map_->height();

      image_32 buf(width,height);

      try
      {
          mapnik::agg_renderer<image_32> ren(*map_,buf,scaling_factor_);
          ren.apply();

          QImage image((uchar*)buf.raw_data(),width,height,QImage::Format_ARGB32);
          pix_=QPixmap::fromImage(image.rgbSwapped());
          projection prj(map_->srs()); // map projection

          box2d<double> ext = map_->get_current_extent();
          double x0 = ext.minx();
          double y0 = ext.miny();
          double x1 = ext.maxx();
          double y1 = ext.maxy();
          prj.inverse(x0,y0);
          prj.inverse(x1,y1);
          std::cout << "BBOX (WGS84): " << x0 << "," << y0 << "," << x1 << "," << y1 << "\n";
          update();
          // emit signal to interested widgets
          emit mapViewChanged();
      }
      catch (mapnik::config_error & ex)
      {
          std::cerr << ex.what() << std::endl;
      }
      catch (...)
      {
          std::cerr << "Unknown exception caught!\n";
      }
   }
}

boost::shared_ptr<Map> MapWidget::getMap()
{
   return map_;
}

void MapWidget::setMap(boost::shared_ptr<Map> map)
{
   map_ = map;
}

void MapWidget::layerSelected(int index)
{
   selectedLayer_ = index;
}
<commit_msg>+ add: #include mapnik/config_error.hpp<commit_after>/* This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2011 Artem Pavlenko
 *
 * Mapnik is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

//$Id$

#include <QtGui>

#include <boost/bind.hpp>

#include <mapnik/agg_renderer.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>
#include <mapnik/ctrans.hpp>
#include <mapnik/memory_datasource.hpp>
#include <mapnik/feature_kv_iterator.hpp>
#include <mapnik/config_error.hpp>
#include "mapwidget.hpp"
#include "info_dialog.hpp"

using mapnik::image_32;
using mapnik::Map;
using mapnik::layer;
using mapnik::box2d;
using mapnik::coord2d;
using mapnik::feature_ptr;
using mapnik::geometry_ptr;
using mapnik::CoordTransform;
using mapnik::projection;
using mapnik::scale_denominator;
using mapnik::feature_kv_iterator;

double scales [] = {279541132.014,
                    139770566.007,
                    69885283.0036,
                    34942641.5018,
                    17471320.7509,
                    8735660.37545,
                    4367830.18772,
                    2183915.09386,
                    1091957.54693,
                    545978.773466,
                    272989.386733,
                    136494.693366,
                    68247.3466832,
                    34123.6733416,
                    17061.8366708,
                    8530.9183354,
                    4265.4591677,
                    2132.72958385,
                    1066.36479192,
                    533.182395962};

MapWidget::MapWidget(QWidget *parent)
   : QWidget(parent),
     map_(),
     selected_(1),
     extent_(),
     cur_tool_(ZoomToBox),
     start_x_(0),
     start_y_(0),
     end_x_(0),
     end_y_(0),
     drag_(false),
     first_(true),
     pen_(QColor(0,0,255,96)),
     selectedLayer_(-1),
     scaling_factor_(1.0)
{
   pen_.setWidth(3);
   pen_.setCapStyle(Qt::RoundCap);
   pen_.setJoinStyle(Qt::RoundJoin);
}

void MapWidget::setTool(eTool tool)
{
   cur_tool_=tool;
}

void MapWidget::paintEvent(QPaintEvent*)
{
   QPainter painter(this);

   if (drag_)
   {
      if (cur_tool_ == ZoomToBox)
      {
         unsigned width = end_x_-start_x_;
         unsigned height = end_y_-start_y_;
         painter.drawPixmap(QPoint(0, 0),pix_);
         painter.setPen(pen_);
         painter.setBrush(QColor(200,200,255,128));
         painter.drawRect(start_x_,start_y_,width,height);
      }
      else if (cur_tool_ == Pan)
      {
         int dx = end_x_-start_x_;
         int dy = end_y_-start_y_;
         painter.setBrush(QColor(200,200,200,128));
         painter.drawRect(0,0,width(),height());
         painter.drawPixmap(QPoint(dx,dy),pix_);
      }
   }
   else
   {
      painter.drawPixmap(QPoint(0, 0),pix_);
   }
   painter.end();
}

void MapWidget::resizeEvent(QResizeEvent * ev)
{
   if (map_)
   {
      map_->resize(ev->size().width(),ev->size().height());
      updateMap();
   }
}

void MapWidget::mousePressEvent(QMouseEvent* e)
{
   if (e->button()==Qt::LeftButton)
   {
      if (cur_tool_ == ZoomToBox || cur_tool_==Pan)
      {
         start_x_ = e->x();
         start_y_ = e->y();
         drag_=true;
      }
      else if (cur_tool_==Info)
      {
         if (map_)
         {
            QVector<QPair<QString,QString> > info;

            projection map_proj(map_->srs()); // map projection
            double scale_denom = scale_denominator(*map_,map_proj.is_geographic());
            CoordTransform t(map_->width(),map_->height(),map_->get_current_extent());

            for (unsigned index = 0; index <  map_->layer_count();++index)
            {
               if (int(index) != selectedLayer_) continue;

               layer & layer = map_->layers()[index];
               if (!layer.visible(scale_denom)) continue;
               std::string name = layer.name();
               double x = e->x();
               double y = e->y();
               std::cout << "query at " << x << "," << y << "\n";
               projection layer_proj(layer.srs());
               mapnik::proj_transform prj_trans(map_proj,layer_proj);
               //std::auto_ptr<mapnik::memory_datasource> data(new mapnik::memory_datasource);
               mapnik::featureset_ptr fs = map_->query_map_point(index,x,y);

               if (fs)
               {
                  feature_ptr feat  = fs->next();
                  if (feat)
                  {

                      feature_kv_iterator itr(*feat,true);
                      feature_kv_iterator end(*feat);

                      for ( ;itr!=end; ++itr)
                      {
                          info.push_back(QPair<QString,QString>(QString(boost::get<0>(*itr).c_str()),
                                                                boost::get<1>(*itr).to_string().c_str()));
                      }

                      typedef mapnik::coord_transform2<mapnik::CoordTransform,mapnik::geometry_type> path_type;

                     for  (unsigned i=0; i<feat->num_geometries();++i)
                     {
                        mapnik::geometry_type & geom = feat->get_geometry(i);
                        path_type path(t,geom,prj_trans);
                        if (geom.num_points() > 0)
                        {
                           QPainterPath qpath;
                           double x,y;
                           path.vertex(&x,&y);
                           qpath.moveTo(x,y);
                           for (unsigned j = 1; j < geom.num_points(); ++j)
                           {
                              path.vertex(&x,&y);
                              qpath.lineTo(x,y);
                           }
                           QPainter painter(&pix_);
                           QPen pen(QColor(255,0,0,96));
                           pen.setWidth(3);
                           pen.setCapStyle(Qt::RoundCap);
                           pen.setJoinStyle(Qt::RoundJoin);
                           painter.setPen(pen);
                           painter.drawPath(qpath);
                           update();
                        }
                     }
                  }
               }

               if (info.size() > 0)
               {
                  info_dialog info_dlg(info,this);
                  info_dlg.exec();
                  break;
               }
            }

            // remove annotation layer
            map_->layers().erase(remove_if(map_->layers().begin(),
                                           map_->layers().end(),
                                           bind(&layer::name,_1) == "*annotations*")
                                 , map_->layers().end());
         }
      }
   }
   else if (e->button()==Qt::RightButton)
   {
      //updateMap();
   }
}

void MapWidget::mouseMoveEvent(QMouseEvent* e)
{
   if (cur_tool_ == ZoomToBox || cur_tool_==Pan)
   {
      end_x_ = e->x();
      end_y_ = e->y();
      update();
   }
}

void MapWidget::mouseReleaseEvent(QMouseEvent* e)
{
   if (e->button()==Qt::LeftButton)
   {
      end_x_ = e->x();
      end_y_ = e->y();
      if (cur_tool_ == ZoomToBox)
      {
         drag_=false;
         if (map_)
         {
            CoordTransform t(map_->width(),map_->height(),map_->get_current_extent());
            box2d<double> box = t.backward(box2d<double>(start_x_,start_y_,end_x_,end_y_));
            map_->zoom_to_box(box);
            updateMap();
         }
      }
      else if (cur_tool_==Pan)
      {
         drag_=false;
         if (map_)
         {
            int cx = int(0.5 * map_->width());
            int cy = int(0.5 * map_->height());
            int dx = end_x_ - start_x_;
            int dy = end_y_ - start_y_;
            map_->pan(cx - dx ,cy - dy);
            updateMap();
         }
      }
   }
}

void MapWidget::keyPressEvent(QKeyEvent *e)
{
   std::cout << "key pressed:"<< e->key()<<"\n";
   switch (e->key()) {
      case Qt::Key_Minus:
         zoomOut();
         break;
      case Qt::Key_Plus:
      case 61:
         zoomIn();
         break;
      case 65:
         defaultView();
         break;
      case Qt::Key_Up:
         panUp();
         break;
      case Qt::Key_Down:
         panDown();
         break;
      case Qt::Key_Left:
         panLeft();
         break;
      case Qt::Key_Right:
         panRight();
         break;
      case 49:
         zoomToLevel(10);
         break;
      case 50:
         zoomToLevel(11);
         break;
      case 51:
         zoomToLevel(12);
         break;
      case 52:
         zoomToLevel(13);
         break;
      case 53:
         zoomToLevel(14);
         break;
      case 54:
         zoomToLevel(15);
         break;
      case 55:
         zoomToLevel(16);
         break;
      case 56:
         zoomToLevel(17);
         break;
      case 57:
         zoomToLevel(18);
         break;
   default:
       QWidget::keyPressEvent(e);
   }

}

void MapWidget::zoomToBox(mapnik::box2d<double> const& bbox)
{
   if (map_)
   {
      map_->zoom_to_box(bbox);
      updateMap();
   }
}

void MapWidget::defaultView()
{
   if (map_)
   {
      map_->resize(width(),height());
      map_->zoom_all();
      updateMap();
   }
}

void MapWidget::zoomIn()
{
   if (map_)
   {
      map_->zoom(0.5);
      updateMap();
   }
}

void MapWidget::zoomOut()
{
   if (map_)
   {
      map_->zoom(2.0);
      updateMap();
   }
}

void MapWidget::panUp()
{
   if (map_)
   {
      double cx = 0.5*map_->width();
      double cy = 0.5*map_->height();
      map_->pan(int(cx),int(cy - cy*0.25));
      updateMap();
   }
}

void MapWidget::panDown()
{
   if (map_)
   {
      double cx = 0.5*map_->width();
      double cy = 0.5*map_->height();
      map_->pan(int(cx),int(cy + cy*0.25));
      updateMap();
   }
}

void MapWidget::panLeft()
{
   if (map_)
   {
      double cx = 0.5*map_->width();
      double cy = 0.5*map_->height();
      map_->pan(int(cx - cx * 0.25),int(cy));
      updateMap();
   }
}

void MapWidget::panRight()
{
   if (map_)
   {
      double cx = 0.5*map_->width();
      double cy = 0.5*map_->height();
      map_->pan(int(cx + cx * 0.25),int(cy));
      updateMap();
   }
}

void MapWidget::zoomToLevel(int level)
{
   if ( map_ && level >= 0 && level < 19 )
   {
      double scale_denom  = scales[level];
      std::cerr << "scale denominator = " << scale_denom << "\n";
      mapnik::box2d<double> ext = map_->get_current_extent();
      double width = static_cast<double>(map_->width());
      double height= static_cast<double>(map_->height());
      mapnik::coord2d pt = ext.center();

      double res = scale_denom * 0.00028;

      mapnik::box2d<double> box(pt.x - 0.5 * width * res,
                                   pt.y - 0.5 * height*res,
                                   pt.x + 0.5 * width * res,
                                   pt.y + 0.5 * height*res);
      map_->zoom_to_box(box);
      updateMap();
   }
}

void MapWidget::export_to_file(unsigned ,unsigned ,std::string const&,std::string const&)
{
   //image_32 image(width,height);
   //agg_renderer renderer(map,image);
   //renderer.apply();
   //image.saveToFile(filename,type);
}

void MapWidget::set_scaling_factor(double scaling_factor)
{
    scaling_factor_ = scaling_factor;
}

void MapWidget::updateMap()
{
   if (map_)
   {
      unsigned width=map_->width();
      unsigned height=map_->height();

      image_32 buf(width,height);

      try
      {
          mapnik::agg_renderer<image_32> ren(*map_,buf,scaling_factor_);
          ren.apply();

          QImage image((uchar*)buf.raw_data(),width,height,QImage::Format_ARGB32);
          pix_=QPixmap::fromImage(image.rgbSwapped());
          projection prj(map_->srs()); // map projection

          box2d<double> ext = map_->get_current_extent();
          double x0 = ext.minx();
          double y0 = ext.miny();
          double x1 = ext.maxx();
          double y1 = ext.maxy();
          prj.inverse(x0,y0);
          prj.inverse(x1,y1);
          std::cout << "BBOX (WGS84): " << x0 << "," << y0 << "," << x1 << "," << y1 << "\n";
          update();
          // emit signal to interested widgets
          emit mapViewChanged();
      }
      catch (mapnik::config_error & ex)
      {
         std::cerr << ex.what() << std::endl;
      }
      catch (...)
      {
          std::cerr << "Unknown exception caught!\n";
      }
   }
}

boost::shared_ptr<Map> MapWidget::getMap()
{
   return map_;
}

void MapWidget::setMap(boost::shared_ptr<Map> map)
{
   map_ = map;
}

void MapWidget::layerSelected(int index)
{
   selectedLayer_ = index;
}
<|endoftext|>


<commit_before>/* -*- Mode: C; indent-tabs-mode: s; c-basic-offset: 4; tab-width: 4 -*- */
/* vim:set et ai sw=4 ts=4 sts=4: tw=80 cino="(0,W2s,i2s,t0,l1,:0" */

#include "wallpaperbusinesslogic.h"
#include "wallpaperdescriptor.h"
#include "wallpapercurrentdescriptor.h"
#include "wallpaperitrans.h"

#include <QDir>
#include <QFile>
#include <QString>
#include <QStringList>
#include <QProcessEnvironment>
#include <QPainter>

#include <Tracker>

#include <MTheme>
#include <MGConfItem>

#define DEBUG
#include "../debug.h"

static const QString PortraitKey =
    "/desktop/meego/background/landscape/picture_filename";
static const QString LandscapeKey =
    "/desktop/meego/background/portrait/picture_filename";

static const QString wallpaperDir = ".wallpapers";
static const QString destopFileName = "wallpaper.desktop";
static const QString backupExtension = ".BAK";

WallpaperBusinessLogic::WallpaperBusinessLogic()
{
    WallpaperCurrentDescriptor *currentDesc;

    m_LandscapeGConfItem = new MGConfItem (LandscapeKey);
    m_PortraitGConfItem = new MGConfItem (PortraitKey);
    m_EditedImage = 0;

    currentDesc = WallpaperCurrentDescriptor::instance ();
    currentDesc->setFromDestopFile (dirPath() + destopFileName);
}

WallpaperBusinessLogic::~WallpaperBusinessLogic()
{
    delete m_LandscapeGConfItem;
    delete m_PortraitGConfItem;
}

/*!
 * FIXME: This method is deprecated, should use the
 * WallpaperCurrentDescriptor::instance () instead.
 */
WallpaperDescriptor *
WallpaperBusinessLogic::Wallpaper (
        bool portrait)
{
    Q_UNUSED (portrait);
    SYS_WARNING ("Deprecated method.");
    return WallpaperCurrentDescriptor::instance ();
}

/*!
 * A high level method to set the current wallpaper.
 */
void
WallpaperBusinessLogic::setBackground (
        WallpaperITrans     *landscapeITrans,
        WallpaperITrans     *portraitITrans,
        WallpaperDescriptor *desc)
{
    bool success;

    SYS_DEBUG ("******** Saving background *********");
    if (desc == 0)
        desc = m_EditedImage;

    Q_ASSERT (landscapeITrans);
    Q_ASSERT (portraitITrans);
    Q_ASSERT (desc);

    success = ensureHasDirectory ();
    if (!success)
        return;

    createBackupFiles ();

    success = writeFiles (landscapeITrans, portraitITrans, desc);
    if (!success) {
        // FIXME: Should restore backup files here.
        return;
    }

    deleteBackupFiles ();

    /*
     *
     */
    WallpaperCurrentDescriptor *currentDesc;
    currentDesc = WallpaperCurrentDescriptor::instance ();
    currentDesc->setFromDestopFile (dirPath() + destopFileName);
    emit wallpaperChanged ();

    SYS_DEBUG ("****** End saving backgroun ********");
}

/*!
 * This function does not support image manipulatios, it is deprecated.
 * FIXME: To remove this function.
 */
void
WallpaperBusinessLogic::setBackground (
        WallpaperDescriptor *desc)
{
    if (desc == 0)
        desc = m_EditedImage;

    SYS_WARNING ("Deprecated method.");
    Q_ASSERT (m_PortraitGConfItem != 0);
    Q_ASSERT (m_LandscapeGConfItem != 0);

    SYS_DEBUG ("*** filename = %s", SYS_STR(desc->filename()));
    m_PortraitGConfItem->set (desc->filename());
    m_LandscapeGConfItem->set (desc->filename());
}

/*!
 * Returns a list wallpaper descriptors with the available wallpapers. The
 * current wallpaper is the first element of the available wallpapers.
 *
 * FIXME: This function needs some polishing.
 */
QList<WallpaperDescriptor *>
WallpaperBusinessLogic::availableWallpapers () const
{
    QList<WallpaperDescriptor *> list;
    const QString query =
"SELECT ?uri ?title ?mime ?height ?width WHERE { "
" ?item nie:url ?uri."

" ?item nie:mimeType ?mime."
" FILTER regex(?mime, \"image\")."

" ?item nfo:height ?height."
" ?item nfo:width ?width."
" FILTER ( ?height > \"300\" )."
" FILTER ( ?width  > \"300\" )."

" OPTIONAL { ?item nie:title ?title }."
"}"
;

    WallpaperCurrentDescriptor *currentDesc;

    currentDesc = WallpaperCurrentDescriptor::instance ();
    list << WallpaperCurrentDescriptor::instance ();

    QVector<QStringList> result = ::tracker()->rawSparqlQuery(query);
    int x = 0;
    int y = 0;

    SYS_WARNING ("*** result.size() = %d", result.size());
    foreach (QStringList partlist, result) {
        WallpaperDescriptor *desc;

        SYS_DEBUG ("*********************************");
        SYS_DEBUG ("*** url     = %s", SYS_STR(partlist[FieldUrl]));

        desc = new WallpaperDescriptor;
        desc->setUrl (partlist[FieldUrl]);
        desc->setTitle (partlist[FieldTitle]);
        desc->setMimeType (partlist[FieldMime]);
        list << desc;

        /*
         * Just to see what we really get.
         */
        #if 1
        foreach (QString element, partlist) {
            SYS_DEBUG ("*** element[%2d][%2d] = %s", x, y, SYS_STR(element));
            x++;
        }
        x = 0;
        #endif

        y++;
    }

    return list;
}

/*!
 * While a wallpaper image is edited the WallpaperBusinessLogic holds a
 * descriptor on it. This function is used to set this wallpaper descriptor.
 */
void
WallpaperBusinessLogic::setEditedImage (
        WallpaperDescriptor  *desc)
{
    SYS_DEBUG ("*** desc = %s", SYS_STR(desc->filename()));
    m_EditedImage = desc;
}

/*!
 * Returns the wallpaper that is being edited.
 */
WallpaperDescriptor *
WallpaperBusinessLogic::editedImage ()
{
    SYS_DEBUG ("*** m_EditedImage = %s", SYS_STR(m_EditedImage->filename()));
    return m_EditedImage;
}

/*********************************************************************************
 * Low level file handling functions.
 */

/*!
 * Returns the directory path that is used to store the information about the
 * edited wallpaper. This is the data storing directory for the wallpaper
 * applet.
 */
QString
WallpaperBusinessLogic::dirPath () const
{
    QString homeDir (getenv("HOME"));
    QString dirPath = homeDir + "/" + wallpaperDir + "/";

    return dirPath;
}

/*!
 * \returns true if the directory exists or could be created
 *
 * If the data store directory does not exists this method will create it.
 */
bool
WallpaperBusinessLogic::ensureHasDirectory ()
{
    QString path = dirPath();
    QDir    dir (path);

    if (dir.exists()) {
        SYS_DEBUG ("Directory %s already exists.", SYS_STR(path));
        return true;
    }

    if (!dir.mkpath(path)) {
        SYS_WARNING ("Unable to create %s directory.", SYS_STR(path));
        return false;
    }

    return true;
}

/*!
 * Takes the desktop file, the saved landscape image file and the saved portrait
 * file and moves/renames them to create a backup version of each of them.
 */
void
WallpaperBusinessLogic::createBackupFiles ()
{
    QString  path = dirPath();
    QString  desktopPath = path + destopFileName;
    QString  filename;

    makeBackup (desktopPath);

    filename = WallpaperCurrentDescriptor::instance()->editedFilename (
            M::Portrait);
    if (!filename.isEmpty())
        makeBackup (filename);

    filename = WallpaperCurrentDescriptor::instance()->editedFilename (
            M::Landscape);
    if (!filename.isEmpty())
        makeBackup (filename);
}

/*!
 * Removes all the files from the applet's data directory that has the file name
 * extension indicating that it is a backup file.
 */
void
WallpaperBusinessLogic::deleteBackupFiles ()
{
    QString     path = dirPath();
    QDir        dir (path);
    QStringList nameFilters ("*.BAK");

    dir.setNameFilters (nameFilters);
    foreach (QString backupFileName, dir.entryList (QDir::Files)) {
        SYS_DEBUG ("Removing backup file %s", SYS_STR(backupFileName));
        QFile backupFile (path + backupFileName);

        if (!backupFile.remove()) {
            SYS_WARNING ("Unable to remove %s backup file.",
                    SYS_STR((path + backupFileName)));
        }
    }
}

/*!
 * \returns true if the files could be created and saved.
 *
 * FIXME: This method should and will be moved to the WallpaperCurrentDescriptor
 * class.
 */
bool
WallpaperBusinessLogic::writeFiles (
        WallpaperITrans     *landscapeITrans,
        WallpaperITrans     *portraitITrans,
        WallpaperDescriptor *desc)
{
    Q_ASSERT (landscapeITrans);
    Q_ASSERT (portraitITrans);
    Q_ASSERT (desc);
    /*
     * These are pretty constants.
     */
    QString  path = dirPath();
    QString  desktopPath = path + destopFileName;
    QFile    file (desktopPath);

    int      version = desc->version () + 1;
    QString  versionString = QString::number(version);
    QString  portraitFilePath = path +
        desc->suggestedOutputFilename (M::Portrait);
    QString  landscapeFilePath = path +
        desc->suggestedOutputFilename (M::Landscape);

    /*
     * Opening the output file.
     */
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        SYS_DEBUG ("Opening file %s for writing failed.", SYS_STR(desktopPath));
        return false;
    }

    /*
     * FIXME: This is the new stuff, but in order to use it the current
     * wallpaper descriptor has to be upgraded with from the arguments of this
     * method.
     */
    QTextStream out(&file);

    QString outString =
        WallpaperCurrentDescriptor::instance()->generateDesktopFile (path);
    SYS_DEBUG ("outString = %s", SYS_STR(outString));

    /*
     * Then this is deprecated.
     */
    out << "[Desktop Entry]\n";
    out << "Type=WallpaperImage\n";
    out << "Name=" << desc->title() << "\n";
    out << "Version=" << QString::number(version) << "\n";
    out << "\n";

    out << "[DCP Landscape Wallpaper]\n";
    out << "OriginalFile=" << desc->originalImageFile(M::Landscape) << "\n";
    out << "EditedFile=" << landscapeFilePath << "\n";
    out << "MimeType=" << desc->mimeType() << "\n";
    out << "HorOffset=" << landscapeITrans->x() << "\n";
    out << "VertOffset=" << landscapeITrans->y() << "\n";
    out << "Scale=" << landscapeITrans->scale() << "\n";
    out << "\n";

    out << "[DCP Portrait Wallpaper]\n";
    out << "OriginalFile=" << desc->originalImageFile(M::Portrait) << "\n";
    out << "EditedFile=" << portraitFilePath << "\n";
    out << "MimeType=" << desc->mimeType() << "\n";
    out << "HorOffset=" << portraitITrans->x() << "\n";
    out << "VertOffset=" << portraitITrans->y() << "\n";
    out << "Scale=" << portraitITrans->scale() << "\n";
    out << "\n";

    makeImageFile (portraitFilePath, desc, portraitITrans);
    makeImageFile (landscapeFilePath, desc, landscapeITrans);

    m_PortraitGConfItem->set (portraitFilePath);
    m_LandscapeGConfItem->set (landscapeFilePath);

    return true;
}

/*!
 * \param filePath The path of the file to save the image into.
 * \param desc The image that should be saved.
 * \param transformations The structure that descibes how to modify the image.
 *
 * This is a low level image manupilation method that takes a wallpaper and
 * saves it into a file with the given manupilations.
 *
 * FIXME: Maybe this method should be moved into some other class?
 */
void
WallpaperBusinessLogic::makeImageFile (
            const QString        &filePath,
            WallpaperDescriptor  *desc,
            WallpaperITrans      *transformations)
{
    QPixmap   pixmap (transformations->expectedSize());
    QPainter  painter (&pixmap);
    qreal     scale = transformations->scale();
    QPixmap   image;
    qreal     ratio, ratio1;

    /*
     * And this is exactly why we should move this kind of stuff into the image
     * descriptor classes.
     */
    if (desc->isCurrent()) {
        WallpaperCurrentDescriptor *cdesc;

        cdesc = qobject_cast<WallpaperCurrentDescriptor*> (desc);
        image.load (cdesc->originalImageFile (transformations->orientation()));
    } else {
        image = desc->pixmap();
    }

    ratio =
        (qreal) transformations->expectedHeight () /
        (qreal) image.height();

    ratio1 =
        (qreal) transformations->expectedWidth () /
        (qreal) image.width();

    if (ratio1 > ratio)
        ratio = ratio1;

    /*
     * Let's fill the pixmap with black, so the area not covered by the original
     * pixmap is initialized.
     */
    pixmap.fill (QColor("black"));

    /*
     * Then we draw the scaled image with the appropriate offset.
     */
    painter.drawPixmap (
                transformations->x(), transformations->y(),
                (scale * image.width ()) * ratio,
                (scale * image.height ()) * ratio,
                image);

    pixmap.save (filePath);
}

/*!
 * Takes a full path file name, removes its backup file if there is one, renames
 * the file to create a backup file.
 */
void
WallpaperBusinessLogic::makeBackup (
        const QString &filePath)
{
    QString  backupFilePath = filePath + backupExtension;
    QFile    file (filePath);
    QFile    backupFile (backupFilePath);

    if (!file.exists())
        return;

    if (backupFile.exists()) {
        if (!backupFile.remove()) {
            SYS_WARNING ("Unable to remove %s backup file.",
                    SYS_STR(backupFilePath));
            return;
        }
    }

    SYS_DEBUG ("Moving %s -> %s", SYS_STR(filePath), SYS_STR(backupFilePath));
    file.rename (backupFilePath);
}

<commit_msg>GConf keys fixed.<commit_after>/* -*- Mode: C; indent-tabs-mode: s; c-basic-offset: 4; tab-width: 4 -*- */
/* vim:set et ai sw=4 ts=4 sts=4: tw=80 cino="(0,W2s,i2s,t0,l1,:0" */

#include "wallpaperbusinesslogic.h"
#include "wallpaperdescriptor.h"
#include "wallpapercurrentdescriptor.h"
#include "wallpaperitrans.h"

#include <QDir>
#include <QFile>
#include <QString>
#include <QStringList>
#include <QProcessEnvironment>
#include <QPainter>

#include <Tracker>

#include <MTheme>
#include <MGConfItem>

#define DEBUG
#include "../debug.h"

static const QString PortraitKey =
    "/desktop/meego/background/portrait/picture_filename";
static const QString LandscapeKey =
    "/desktop/meego/background/landscape/picture_filename";

static const QString wallpaperDir = ".wallpapers";
static const QString destopFileName = "wallpaper.desktop";
static const QString backupExtension = ".BAK";

WallpaperBusinessLogic::WallpaperBusinessLogic()
{
    WallpaperCurrentDescriptor *currentDesc;

    m_LandscapeGConfItem = new MGConfItem (LandscapeKey);
    m_PortraitGConfItem = new MGConfItem (PortraitKey);
    m_EditedImage = 0;

    currentDesc = WallpaperCurrentDescriptor::instance ();
    currentDesc->setFromDestopFile (dirPath() + destopFileName);
}

WallpaperBusinessLogic::~WallpaperBusinessLogic()
{
    delete m_LandscapeGConfItem;
    delete m_PortraitGConfItem;
}

/*!
 * FIXME: This method is deprecated, should use the
 * WallpaperCurrentDescriptor::instance () instead.
 */
WallpaperDescriptor *
WallpaperBusinessLogic::Wallpaper (
        bool portrait)
{
    Q_UNUSED (portrait);
    SYS_WARNING ("Deprecated method.");
    return WallpaperCurrentDescriptor::instance ();
}

/*!
 * A high level method to set the current wallpaper.
 */
void
WallpaperBusinessLogic::setBackground (
        WallpaperITrans     *landscapeITrans,
        WallpaperITrans     *portraitITrans,
        WallpaperDescriptor *desc)
{
    bool success;

    SYS_DEBUG ("******** Saving background *********");
    if (desc == 0)
        desc = m_EditedImage;

    Q_ASSERT (landscapeITrans);
    Q_ASSERT (portraitITrans);
    Q_ASSERT (desc);

    success = ensureHasDirectory ();
    if (!success)
        return;

    createBackupFiles ();

    success = writeFiles (landscapeITrans, portraitITrans, desc);
    if (!success) {
        // FIXME: Should restore backup files here.
        return;
    }

    deleteBackupFiles ();

    /*
     *
     */
    WallpaperCurrentDescriptor *currentDesc;
    currentDesc = WallpaperCurrentDescriptor::instance ();
    currentDesc->setFromDestopFile (dirPath() + destopFileName);
    emit wallpaperChanged ();

    SYS_DEBUG ("****** End saving backgroun ********");
}

/*!
 * This function does not support image manipulatios, it is deprecated.
 * FIXME: To remove this function.
 */
void
WallpaperBusinessLogic::setBackground (
        WallpaperDescriptor *desc)
{
    if (desc == 0)
        desc = m_EditedImage;

    SYS_WARNING ("Deprecated method.");
    Q_ASSERT (m_PortraitGConfItem != 0);
    Q_ASSERT (m_LandscapeGConfItem != 0);

    SYS_DEBUG ("*** filename = %s", SYS_STR(desc->filename()));
    m_PortraitGConfItem->set (desc->filename());
    m_LandscapeGConfItem->set (desc->filename());
}

/*!
 * Returns a list wallpaper descriptors with the available wallpapers. The
 * current wallpaper is the first element of the available wallpapers.
 *
 * FIXME: This function needs some polishing.
 */
QList<WallpaperDescriptor *>
WallpaperBusinessLogic::availableWallpapers () const
{
    QList<WallpaperDescriptor *> list;
    const QString query =
"SELECT ?uri ?title ?mime ?height ?width WHERE { "
" ?item nie:url ?uri."

" ?item nie:mimeType ?mime."
" FILTER regex(?mime, \"image\")."

" ?item nfo:height ?height."
" ?item nfo:width ?width."
" FILTER ( ?height > \"300\" )."
" FILTER ( ?width  > \"300\" )."

" OPTIONAL { ?item nie:title ?title }."
"}"
;

    WallpaperCurrentDescriptor *currentDesc;

    currentDesc = WallpaperCurrentDescriptor::instance ();
    list << WallpaperCurrentDescriptor::instance ();

    QVector<QStringList> result = ::tracker()->rawSparqlQuery(query);
    int x = 0;
    int y = 0;

    SYS_WARNING ("*** result.size() = %d", result.size());
    foreach (QStringList partlist, result) {
        WallpaperDescriptor *desc;

        SYS_DEBUG ("*********************************");
        SYS_DEBUG ("*** url     = %s", SYS_STR(partlist[FieldUrl]));

        desc = new WallpaperDescriptor;
        desc->setUrl (partlist[FieldUrl]);
        desc->setTitle (partlist[FieldTitle]);
        desc->setMimeType (partlist[FieldMime]);
        list << desc;

        /*
         * Just to see what we really get.
         */
        #if 1
        foreach (QString element, partlist) {
            SYS_DEBUG ("*** element[%2d][%2d] = %s", x, y, SYS_STR(element));
            x++;
        }
        x = 0;
        #endif

        y++;
    }

    return list;
}

/*!
 * While a wallpaper image is edited the WallpaperBusinessLogic holds a
 * descriptor on it. This function is used to set this wallpaper descriptor.
 */
void
WallpaperBusinessLogic::setEditedImage (
        WallpaperDescriptor  *desc)
{
    SYS_DEBUG ("*** desc = %s", SYS_STR(desc->filename()));
    m_EditedImage = desc;
}

/*!
 * Returns the wallpaper that is being edited.
 */
WallpaperDescriptor *
WallpaperBusinessLogic::editedImage ()
{
    SYS_DEBUG ("*** m_EditedImage = %s", SYS_STR(m_EditedImage->filename()));
    return m_EditedImage;
}

/*********************************************************************************
 * Low level file handling functions.
 */

/*!
 * Returns the directory path that is used to store the information about the
 * edited wallpaper. This is the data storing directory for the wallpaper
 * applet.
 */
QString
WallpaperBusinessLogic::dirPath () const
{
    QString homeDir (getenv("HOME"));
    QString dirPath = homeDir + "/" + wallpaperDir + "/";

    return dirPath;
}

/*!
 * \returns true if the directory exists or could be created
 *
 * If the data store directory does not exists this method will create it.
 */
bool
WallpaperBusinessLogic::ensureHasDirectory ()
{
    QString path = dirPath();
    QDir    dir (path);

    if (dir.exists()) {
        SYS_DEBUG ("Directory %s already exists.", SYS_STR(path));
        return true;
    }

    if (!dir.mkpath(path)) {
        SYS_WARNING ("Unable to create %s directory.", SYS_STR(path));
        return false;
    }

    return true;
}

/*!
 * Takes the desktop file, the saved landscape image file and the saved portrait
 * file and moves/renames them to create a backup version of each of them.
 */
void
WallpaperBusinessLogic::createBackupFiles ()
{
    QString  path = dirPath();
    QString  desktopPath = path + destopFileName;
    QString  filename;

    makeBackup (desktopPath);

    filename = WallpaperCurrentDescriptor::instance()->editedFilename (
            M::Portrait);
    if (!filename.isEmpty())
        makeBackup (filename);

    filename = WallpaperCurrentDescriptor::instance()->editedFilename (
            M::Landscape);
    if (!filename.isEmpty())
        makeBackup (filename);
}

/*!
 * Removes all the files from the applet's data directory that has the file name
 * extension indicating that it is a backup file.
 */
void
WallpaperBusinessLogic::deleteBackupFiles ()
{
    QString     path = dirPath();
    QDir        dir (path);
    QStringList nameFilters ("*.BAK");

    dir.setNameFilters (nameFilters);
    foreach (QString backupFileName, dir.entryList (QDir::Files)) {
        SYS_DEBUG ("Removing backup file %s", SYS_STR(backupFileName));
        QFile backupFile (path + backupFileName);

        if (!backupFile.remove()) {
            SYS_WARNING ("Unable to remove %s backup file.",
                    SYS_STR((path + backupFileName)));
        }
    }
}

/*!
 * \returns true if the files could be created and saved.
 *
 * FIXME: This method should and will be moved to the WallpaperCurrentDescriptor
 * class.
 */
bool
WallpaperBusinessLogic::writeFiles (
        WallpaperITrans     *landscapeITrans,
        WallpaperITrans     *portraitITrans,
        WallpaperDescriptor *desc)
{
    Q_ASSERT (landscapeITrans);
    Q_ASSERT (portraitITrans);
    Q_ASSERT (desc);
    /*
     * These are pretty constants.
     */
    QString  path = dirPath();
    QString  desktopPath = path + destopFileName;
    QFile    file (desktopPath);

    int      version = desc->version () + 1;
    QString  versionString = QString::number(version);
    QString  portraitFilePath = path +
        desc->suggestedOutputFilename (M::Portrait);
    QString  landscapeFilePath = path +
        desc->suggestedOutputFilename (M::Landscape);

    /*
     * Opening the output file.
     */
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
        SYS_DEBUG ("Opening file %s for writing failed.", SYS_STR(desktopPath));
        return false;
    }

    /*
     * FIXME: This is the new stuff, but in order to use it the current
     * wallpaper descriptor has to be upgraded with from the arguments of this
     * method.
     */
    QTextStream out(&file);

    QString outString =
        WallpaperCurrentDescriptor::instance()->generateDesktopFile (path);
    SYS_DEBUG ("outString = %s", SYS_STR(outString));

    /*
     * Then this is deprecated.
     */
    out << "[Desktop Entry]\n";
    out << "Type=WallpaperImage\n";
    out << "Name=" << desc->title() << "\n";
    out << "Version=" << QString::number(version) << "\n";
    out << "\n";

    out << "[DCP Landscape Wallpaper]\n";
    out << "OriginalFile=" << desc->originalImageFile(M::Landscape) << "\n";
    out << "EditedFile=" << landscapeFilePath << "\n";
    out << "MimeType=" << desc->mimeType() << "\n";
    out << "HorOffset=" << landscapeITrans->x() << "\n";
    out << "VertOffset=" << landscapeITrans->y() << "\n";
    out << "Scale=" << landscapeITrans->scale() << "\n";
    out << "\n";

    out << "[DCP Portrait Wallpaper]\n";
    out << "OriginalFile=" << desc->originalImageFile(M::Portrait) << "\n";
    out << "EditedFile=" << portraitFilePath << "\n";
    out << "MimeType=" << desc->mimeType() << "\n";
    out << "HorOffset=" << portraitITrans->x() << "\n";
    out << "VertOffset=" << portraitITrans->y() << "\n";
    out << "Scale=" << portraitITrans->scale() << "\n";
    out << "\n";

    makeImageFile (portraitFilePath, desc, portraitITrans);
    makeImageFile (landscapeFilePath, desc, landscapeITrans);

    m_PortraitGConfItem->set (portraitFilePath);
    m_LandscapeGConfItem->set (landscapeFilePath);

    return true;
}

/*!
 * \param filePath The path of the file to save the image into.
 * \param desc The image that should be saved.
 * \param transformations The structure that descibes how to modify the image.
 *
 * This is a low level image manupilation method that takes a wallpaper and
 * saves it into a file with the given manupilations.
 *
 * FIXME: Maybe this method should be moved into some other class?
 */
void
WallpaperBusinessLogic::makeImageFile (
            const QString        &filePath,
            WallpaperDescriptor  *desc,
            WallpaperITrans      *transformations)
{
    QPixmap   pixmap (transformations->expectedSize());
    QPainter  painter (&pixmap);
    qreal     scale = transformations->scale();
    QPixmap   image;
    qreal     ratio, ratio1;

    /*
     * And this is exactly why we should move this kind of stuff into the image
     * descriptor classes.
     */
    if (desc->isCurrent()) {
        WallpaperCurrentDescriptor *cdesc;

        cdesc = qobject_cast<WallpaperCurrentDescriptor*> (desc);
        image.load (cdesc->originalImageFile (transformations->orientation()));
    } else {
        image = desc->pixmap();
    }

    ratio =
        (qreal) transformations->expectedHeight () /
        (qreal) image.height();

    ratio1 =
        (qreal) transformations->expectedWidth () /
        (qreal) image.width();

    if (ratio1 > ratio)
        ratio = ratio1;

    /*
     * Let's fill the pixmap with black, so the area not covered by the original
     * pixmap is initialized.
     */
    pixmap.fill (QColor("black"));

    /*
     * Then we draw the scaled image with the appropriate offset.
     */
    painter.drawPixmap (
                transformations->x(), transformations->y(),
                (scale * image.width ()) * ratio,
                (scale * image.height ()) * ratio,
                image);

    pixmap.save (filePath);
}

/*!
 * Takes a full path file name, removes its backup file if there is one, renames
 * the file to create a backup file.
 */
void
WallpaperBusinessLogic::makeBackup (
        const QString &filePath)
{
    QString  backupFilePath = filePath + backupExtension;
    QFile    file (filePath);
    QFile    backupFile (backupFilePath);

    if (!file.exists())
        return;

    if (backupFile.exists()) {
        if (!backupFile.remove()) {
            SYS_WARNING ("Unable to remove %s backup file.",
                    SYS_STR(backupFilePath));
            return;
        }
    }

    SYS_DEBUG ("Moving %s -> %s", SYS_STR(filePath), SYS_STR(backupFilePath));
    file.rename (backupFilePath);
}

<|endoftext|>


<commit_before>//===- DeadMachineInstructionElim.cpp - Remove dead machine instructions --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is an extremely simple MachineInstr-level dead-code-elimination pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/Pass.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

namespace {
  class DeadMachineInstructionElim : public MachineFunctionPass {
    virtual bool runOnMachineFunction(MachineFunction &MF);

    const TargetRegisterInfo *TRI;
    const MachineRegisterInfo *MRI;
    const TargetInstrInfo *TII;
    BitVector LivePhysRegs;

  public:
    static char ID; // Pass identification, replacement for typeid
    DeadMachineInstructionElim() : MachineFunctionPass(&ID) {}

  private:
    bool isDead(const MachineInstr *MI) const;
  };
}
char DeadMachineInstructionElim::ID = 0;

static RegisterPass<DeadMachineInstructionElim>
Y("dead-mi-elimination",
  "Remove dead machine instructions");

FunctionPass *llvm::createDeadMachineInstructionElimPass() {
  return new DeadMachineInstructionElim();
}

bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const {
  // Don't delete instructions with side effects.
  bool SawStore = false;
  if (!MI->isSafeToMove(TII, SawStore, 0))
    return false;

  // Examine each operand.
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (MO.isReg() && MO.isDef()) {
      unsigned Reg = MO.getReg();
      if (TargetRegisterInfo::isPhysicalRegister(Reg) ?
          LivePhysRegs[Reg] : !MRI->use_empty(Reg)) {
        // This def has a use. Don't delete the instruction!
        return false;
      }
    }
  }

  // If there are no defs with uses, the instruction is dead.
  return true;
}

bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) {
  bool AnyChanges = false;
  MRI = &MF.getRegInfo();
  TRI = MF.getTarget().getRegisterInfo();
  TII = MF.getTarget().getInstrInfo();

  // Compute a bitvector to represent all non-allocatable physregs.
  BitVector NonAllocatableRegs = TRI->getAllocatableSet(MF);
  NonAllocatableRegs.flip();

  // Loop over all instructions in all blocks, from bottom to top, so that it's
  // more likely that chains of dependent but ultimately dead instructions will
  // be cleaned up.
  for (MachineFunction::reverse_iterator I = MF.rbegin(), E = MF.rend();
       I != E; ++I) {
    MachineBasicBlock *MBB = &*I;

    // Start out assuming that all non-allocatable registers are live
    // out of this block.
    LivePhysRegs = NonAllocatableRegs;

    // Also add any explicit live-out physregs for this block.
    if (!MBB->empty() && MBB->back().getDesc().isReturn())
      for (MachineRegisterInfo::liveout_iterator LOI = MRI->liveout_begin(),
           LOE = MRI->liveout_end(); LOI != LOE; ++LOI) {
        unsigned Reg = *LOI;
        if (TargetRegisterInfo::isPhysicalRegister(Reg))
          LivePhysRegs.set(Reg);
      }

    // Now scan the instructions and delete dead ones, tracking physreg
    // liveness as we go.
    for (MachineBasicBlock::reverse_iterator MII = MBB->rbegin(),
         MIE = MBB->rend(); MII != MIE; ) {
      MachineInstr *MI = &*MII;

      // If the instruction is dead, delete it!
      if (isDead(MI)) {
        DEBUG(dbgs() << "DeadMachineInstructionElim: DELETING: " << *MI);
        AnyChanges = true;
        MI->eraseFromParent();
        MIE = MBB->rend();
        // MII is now pointing to the next instruction to process,
        // so don't increment it.
        continue;
      }

      // Record the physreg defs.
      for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
        const MachineOperand &MO = MI->getOperand(i);
        if (MO.isReg() && MO.isDef()) {
          unsigned Reg = MO.getReg();
          if (Reg != 0 && TargetRegisterInfo::isPhysicalRegister(Reg)) {
            LivePhysRegs.reset(Reg);
            // Check the subreg set, not the alias set, because a def
            // of a super-register may still be partially live after
            // this def.
            for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
                 *SubRegs; ++SubRegs)
              LivePhysRegs.reset(*SubRegs);
          }
        }
      }
      // Record the physreg uses, after the defs, in case a physreg is
      // both defined and used in the same instruction.
      for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
        const MachineOperand &MO = MI->getOperand(i);
        if (MO.isReg() && MO.isUse()) {
          unsigned Reg = MO.getReg();
          if (Reg != 0 && TargetRegisterInfo::isPhysicalRegister(Reg)) {
            LivePhysRegs.set(Reg);
            for (const unsigned *AliasSet = TRI->getAliasSet(Reg);
                 *AliasSet; ++AliasSet)
              LivePhysRegs.set(*AliasSet);
          }
        }
      }

      // We didn't delete the current instruction, so increment MII to
      // the next one.
      ++MII;
    }
  }

  LivePhysRegs.clear();
  return AnyChanges;
}
<commit_msg>If the only use of something is a DEBUG_VALUE, don't let that stop it from being deleted, and change the DEBUG_VALUE value to undef.<commit_after>//===- DeadMachineInstructionElim.cpp - Remove dead machine instructions --===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This is an extremely simple MachineInstr-level dead-code-elimination pass.
//
//===----------------------------------------------------------------------===//

#include "llvm/CodeGen/Passes.h"
#include "llvm/Pass.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Target/TargetInstrInfo.h"
#include "llvm/Target/TargetMachine.h"
using namespace llvm;

namespace {
  class DeadMachineInstructionElim : public MachineFunctionPass {
    virtual bool runOnMachineFunction(MachineFunction &MF);

    const TargetRegisterInfo *TRI;
    const MachineRegisterInfo *MRI;
    const TargetInstrInfo *TII;
    BitVector LivePhysRegs;

  public:
    static char ID; // Pass identification, replacement for typeid
    DeadMachineInstructionElim() : MachineFunctionPass(&ID) {}

  private:
    bool isDead(const MachineInstr *MI) const;
  };
}
char DeadMachineInstructionElim::ID = 0;

static RegisterPass<DeadMachineInstructionElim>
Y("dead-mi-elimination",
  "Remove dead machine instructions");

FunctionPass *llvm::createDeadMachineInstructionElimPass() {
  return new DeadMachineInstructionElim();
}

bool DeadMachineInstructionElim::isDead(const MachineInstr *MI) const {
  // Don't delete instructions with side effects.
  bool SawStore = false;
  if (!MI->isSafeToMove(TII, SawStore, 0))
    return false;

  // Examine each operand.
  for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
    const MachineOperand &MO = MI->getOperand(i);
    if (MO.isReg() && MO.isDef()) {
      unsigned Reg = MO.getReg();
      if (TargetRegisterInfo::isPhysicalRegister(Reg) ?
          LivePhysRegs[Reg] : !MRI->use_empty(Reg)) {
        // This def has a use. Don't delete the instruction!
        return false;
      }
    }
  }

  // If there are no defs with uses, the instruction is dead.
  return true;
}

bool DeadMachineInstructionElim::runOnMachineFunction(MachineFunction &MF) {
  bool AnyChanges = false;
  MRI = &MF.getRegInfo();
  TRI = MF.getTarget().getRegisterInfo();
  TII = MF.getTarget().getInstrInfo();

  // Compute a bitvector to represent all non-allocatable physregs.
  BitVector NonAllocatableRegs = TRI->getAllocatableSet(MF);
  NonAllocatableRegs.flip();

  // Loop over all instructions in all blocks, from bottom to top, so that it's
  // more likely that chains of dependent but ultimately dead instructions will
  // be cleaned up.
  for (MachineFunction::reverse_iterator I = MF.rbegin(), E = MF.rend();
       I != E; ++I) {
    MachineBasicBlock *MBB = &*I;

    // Start out assuming that all non-allocatable registers are live
    // out of this block.
    LivePhysRegs = NonAllocatableRegs;

    // Also add any explicit live-out physregs for this block.
    if (!MBB->empty() && MBB->back().getDesc().isReturn())
      for (MachineRegisterInfo::liveout_iterator LOI = MRI->liveout_begin(),
           LOE = MRI->liveout_end(); LOI != LOE; ++LOI) {
        unsigned Reg = *LOI;
        if (TargetRegisterInfo::isPhysicalRegister(Reg))
          LivePhysRegs.set(Reg);
      }

    // Now scan the instructions and delete dead ones, tracking physreg
    // liveness as we go.
    for (MachineBasicBlock::reverse_iterator MII = MBB->rbegin(),
         MIE = MBB->rend(); MII != MIE; ) {
      MachineInstr *MI = &*MII;

      if (MI->getOpcode()==TargetInstrInfo::DEBUG_VALUE) {
        // Don't delete the DEBUG_VALUE itself, but if its Value operand is
        // a vreg and this is the only use, substitute an undef operand;
        // the former operand will then be deleted normally.
        if (MI->getNumOperands()==3 && MI->getOperand(0).isReg()) {
          unsigned Reg = MI->getOperand(0).getReg();
          MachineRegisterInfo::use_iterator I = MRI->use_begin(Reg);
          assert(I != MRI->use_end());
          if (++I == MRI->use_end())
            // only one use, which must be this DEBUG_VALUE.
            MI->getOperand(0).setReg(0U);
        }
      }

      // If the instruction is dead, delete it!
      if (isDead(MI)) {
        DEBUG(dbgs() << "DeadMachineInstructionElim: DELETING: " << *MI);
        AnyChanges = true;
        MI->eraseFromParent();
        MIE = MBB->rend();
        // MII is now pointing to the next instruction to process,
        // so don't increment it.
        continue;
      }

      // Record the physreg defs.
      for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
        const MachineOperand &MO = MI->getOperand(i);
        if (MO.isReg() && MO.isDef()) {
          unsigned Reg = MO.getReg();
          if (Reg != 0 && TargetRegisterInfo::isPhysicalRegister(Reg)) {
            LivePhysRegs.reset(Reg);
            // Check the subreg set, not the alias set, because a def
            // of a super-register may still be partially live after
            // this def.
            for (const unsigned *SubRegs = TRI->getSubRegisters(Reg);
                 *SubRegs; ++SubRegs)
              LivePhysRegs.reset(*SubRegs);
          }
        }
      }
      // Record the physreg uses, after the defs, in case a physreg is
      // both defined and used in the same instruction.
      for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
        const MachineOperand &MO = MI->getOperand(i);
        if (MO.isReg() && MO.isUse()) {
          unsigned Reg = MO.getReg();
          if (Reg != 0 && TargetRegisterInfo::isPhysicalRegister(Reg)) {
            LivePhysRegs.set(Reg);
            for (const unsigned *AliasSet = TRI->getAliasSet(Reg);
                 *AliasSet; ++AliasSet)
              LivePhysRegs.set(*AliasSet);
          }
        }
      }

      // We didn't delete the current instruction, so increment MII to
      // the next one.
      ++MII;
    }
  }

  LivePhysRegs.clear();
  return AnyChanges;
}
<|endoftext|>


<commit_before>//===- DependenceAnalysis.cpp - Dependence analysis on SSA views ----------===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// This file implements view-based alias and dependence analyses.
//
//===----------------------------------------------------------------------===//

#include "mlir/Linalg/Analysis/DependenceAnalysis.h"
#include "mlir/Linalg/IR/LinalgOps.h"

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"

#define DEBUG_TYPE "linalg-dependence-analysis"

using namespace mlir;
using namespace mlir::linalg;

using llvm::dbgs;

Value *Aliases::find(Value *v) {
  if (v->getKind() == Value::Kind::BlockArgument)
    return v;

  auto it = aliases.find(v);
  if (it != aliases.end()) {
    assert((it->getSecond()->getKind() == Value::Kind::BlockArgument &&
            it->getSecond()->getType().isa<ViewType>()) ||
           it->getSecond()->getType().isa<BufferType>() &&
               "Buffer or block argument expected");
    return it->getSecond();
  }
  if (auto slice = dyn_cast_or_null<SliceOp>(v->getDefiningOp())) {
    auto it = aliases.insert(std::make_pair(v, find(slice.getBaseView())));
    return it.first->second;
  }
  if (auto view = dyn_cast_or_null<ViewOp>(v->getDefiningOp())) {
    auto it = aliases.insert(std::make_pair(v, view.getSupportingBuffer()));
    return it.first->second;
  }
  llvm_unreachable("unsupported view alias case");
}

LinalgDependenceGraph::LinalgDependenceGraph(Aliases &aliases,
                                             ArrayRef<Operation *> ops)
    : aliases(aliases), linalgOps(ops.begin(), ops.end()) {
  for (auto en : llvm::enumerate(linalgOps)) {
    assert(isa<LinalgOp>(en.value()) && "Expected value for LinalgOp");
    linalgOpPositions.insert(make_pair(en.value(), en.index()));
  }
  for (unsigned i = 0, e = ops.size(); i < e; ++i) {
    for (unsigned j = i + 1; j < e; ++j) {
      addDependencesBetween(cast<LinalgOp>(ops[i]), cast<LinalgOp>(ops[j]));
    }
  }
}

void LinalgDependenceGraph::addDependenceElem(DependenceType dt,
                                              LinalgOpView indexingOpView,
                                              LinalgOpView dependentOpView) {
  LLVM_DEBUG(dbgs() << "\nAdd dep type " << dt << ":\t" << *indexingOpView.op
                    << " -> " << *dependentOpView.op);
  dependencesFromGraphs[dt][indexingOpView.op].push_back(
      LinalgDependenceGraphElem{dependentOpView, indexingOpView.view});
  dependencesIntoGraphs[dt][dependentOpView.op].push_back(
      LinalgDependenceGraphElem{indexingOpView, dependentOpView.view});
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesFrom(
    LinalgOp src, LinalgDependenceGraph::DependenceType dt) {
  return getDependencesFrom(src.getOperation(), dt);
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesFrom(
    Operation *src, LinalgDependenceGraph::DependenceType dt) {
  auto &vec = dependencesFromGraphs[dt][src];
  return llvm::make_range(vec.begin(), vec.end());
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesInto(
    LinalgOp dst, LinalgDependenceGraph::DependenceType dt) {
  return getDependencesInto(dst.getOperation(), dt);
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesInto(
    Operation *dst, LinalgDependenceGraph::DependenceType dt) {
  auto &vec = dependencesIntoGraphs[dt][dst];
  return llvm::make_range(vec.begin(), vec.end());
}

void LinalgDependenceGraph::addDependencesBetween(LinalgOp src, LinalgOp dst) {
  for (auto *srcView : src.getOutputs()) { // W
    // RAW graph
    for (auto *dstView : dst.getInputs()) {  // R
      if (aliases.alias(srcView, dstView)) { // if alias, fill RAW
        addDependenceElem(DependenceType::RAW,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
    // WAW graph
    for (auto *dstView : dst.getOutputs()) { // W
      if (aliases.alias(srcView, dstView)) { // if alias, fill WAW
        addDependenceElem(DependenceType::WAW,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
  }
  for (auto *srcView : src.getInputs()) { // R
    // RAR graph
    for (auto *dstView : dst.getInputs()) {  // R
      if (aliases.alias(srcView, dstView)) { // if alias, fill RAR
        addDependenceElem(DependenceType::RAR,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
    // WAR graph
    for (auto *dstView : dst.getOutputs()) { // W
      if (aliases.alias(srcView, dstView)) { // if alias, fill WAR
        addDependenceElem(DependenceType::WAR,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
  }
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findCoveringDependences(LinalgOp srcLinalgOp,
                                               LinalgOp dstLinalgOp) {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, nullptr,
      {DependenceType::WAW, DependenceType::WAR, DependenceType::RAW});
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findCoveringWrites(LinalgOp srcLinalgOp,
                                          LinalgOp dstLinalgOp, Value *view) {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, view,
      {DependenceType::WAW, DependenceType::WAR});
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findCoveringReads(LinalgOp srcLinalgOp,
                                         LinalgOp dstLinalgOp, Value *view) {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, view,
      {DependenceType::RAR, DependenceType::RAW});
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findOperationsWithCoveringDependences(
    LinalgOp srcLinalgOp, LinalgOp dstLinalgOp, Value *view,
    ArrayRef<DependenceType> types) {
  auto *src = srcLinalgOp.getOperation();
  auto *dst = dstLinalgOp.getOperation();
  auto srcPos = linalgOpPositions[src];
  auto dstPos = linalgOpPositions[dst];
  assert(srcPos < dstPos && "expected dst after src in IR traversal order");

  SmallVector<Operation *, 8> res;
  // Consider an intermediate interleaved `interim` op, look for any dependence
  // to an aliasing view on a src -> op -> dst path.
  // TODO(ntv) we are not considering paths yet, just interleaved positions.
  for (auto dt : types) {
    for (auto dependence : getDependencesFrom(src, dt)) {
      auto interimPos = linalgOpPositions[dependence.dependentOpView.op];
      // Skip if not interleaved.
      if (interimPos >= dstPos || interimPos <= srcPos)
        continue;
      if (view && !aliases.alias(view, dependence.indexingView))
        continue;
      auto *op = dependence.dependentOpView.op;
      LLVM_DEBUG(dbgs() << "\n***Found covering dependence of type " << dt
                        << ": " << *src << " -> " << *op << " on "
                        << *dependence.indexingView);
      res.push_back(op);
    }
  }
  return res;
}
<commit_msg>Fix OSS build<commit_after>//===- DependenceAnalysis.cpp - Dependence analysis on SSA views ----------===//
//
// Copyright 2019 The MLIR Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// =============================================================================
//
// This file implements view-based alias and dependence analyses.
//
//===----------------------------------------------------------------------===//

#include "mlir/Linalg/Analysis/DependenceAnalysis.h"
#include "mlir/Linalg/IR/LinalgOps.h"

#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"

#define DEBUG_TYPE "linalg-dependence-analysis"

using namespace mlir;
using namespace mlir::linalg;

using llvm::dbgs;

Value *Aliases::find(Value *v) {
  if (v->getKind() == Value::Kind::BlockArgument)
    return v;

  auto it = aliases.find(v);
  if (it != aliases.end()) {
    assert(((it->getSecond()->getKind() == Value::Kind::BlockArgument &&
             it->getSecond()->getType().isa<ViewType>()) ||
            it->getSecond()->getType().isa<BufferType>()) &&
           "Buffer or block argument expected");
    return it->getSecond();
  }
  if (auto slice = dyn_cast_or_null<SliceOp>(v->getDefiningOp())) {
    auto it = aliases.insert(std::make_pair(v, find(slice.getBaseView())));
    return it.first->second;
  }
  if (auto view = dyn_cast_or_null<ViewOp>(v->getDefiningOp())) {
    auto it = aliases.insert(std::make_pair(v, view.getSupportingBuffer()));
    return it.first->second;
  }
  llvm_unreachable("unsupported view alias case");
}

LinalgDependenceGraph::LinalgDependenceGraph(Aliases &aliases,
                                             ArrayRef<Operation *> ops)
    : aliases(aliases), linalgOps(ops.begin(), ops.end()) {
  for (auto en : llvm::enumerate(linalgOps)) {
    assert(isa<LinalgOp>(en.value()) && "Expected value for LinalgOp");
    linalgOpPositions.insert(std::make_pair(en.value(), en.index()));
  }
  for (unsigned i = 0, e = ops.size(); i < e; ++i) {
    for (unsigned j = i + 1; j < e; ++j) {
      addDependencesBetween(cast<LinalgOp>(ops[i]), cast<LinalgOp>(ops[j]));
    }
  }
}

void LinalgDependenceGraph::addDependenceElem(DependenceType dt,
                                              LinalgOpView indexingOpView,
                                              LinalgOpView dependentOpView) {
  LLVM_DEBUG(dbgs() << "\nAdd dep type " << dt << ":\t" << *indexingOpView.op
                    << " -> " << *dependentOpView.op);
  dependencesFromGraphs[dt][indexingOpView.op].push_back(
      LinalgDependenceGraphElem{dependentOpView, indexingOpView.view});
  dependencesIntoGraphs[dt][dependentOpView.op].push_back(
      LinalgDependenceGraphElem{indexingOpView, dependentOpView.view});
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesFrom(
    LinalgOp src, LinalgDependenceGraph::DependenceType dt) {
  return getDependencesFrom(src.getOperation(), dt);
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesFrom(
    Operation *src, LinalgDependenceGraph::DependenceType dt) {
  auto &vec = dependencesFromGraphs[dt][src];
  return llvm::make_range(vec.begin(), vec.end());
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesInto(
    LinalgOp dst, LinalgDependenceGraph::DependenceType dt) {
  return getDependencesInto(dst.getOperation(), dt);
}

LinalgDependenceGraph::dependence_range
LinalgDependenceGraph::getDependencesInto(
    Operation *dst, LinalgDependenceGraph::DependenceType dt) {
  auto &vec = dependencesIntoGraphs[dt][dst];
  return llvm::make_range(vec.begin(), vec.end());
}

void LinalgDependenceGraph::addDependencesBetween(LinalgOp src, LinalgOp dst) {
  for (auto *srcView : src.getOutputs()) { // W
    // RAW graph
    for (auto *dstView : dst.getInputs()) {  // R
      if (aliases.alias(srcView, dstView)) { // if alias, fill RAW
        addDependenceElem(DependenceType::RAW,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
    // WAW graph
    for (auto *dstView : dst.getOutputs()) { // W
      if (aliases.alias(srcView, dstView)) { // if alias, fill WAW
        addDependenceElem(DependenceType::WAW,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
  }
  for (auto *srcView : src.getInputs()) { // R
    // RAR graph
    for (auto *dstView : dst.getInputs()) {  // R
      if (aliases.alias(srcView, dstView)) { // if alias, fill RAR
        addDependenceElem(DependenceType::RAR,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
    // WAR graph
    for (auto *dstView : dst.getOutputs()) { // W
      if (aliases.alias(srcView, dstView)) { // if alias, fill WAR
        addDependenceElem(DependenceType::WAR,
                          LinalgOpView{src.getOperation(), srcView},
                          LinalgOpView{dst.getOperation(), dstView});
      }
    }
  }
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findCoveringDependences(LinalgOp srcLinalgOp,
                                               LinalgOp dstLinalgOp) {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, nullptr,
      {DependenceType::WAW, DependenceType::WAR, DependenceType::RAW});
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findCoveringWrites(LinalgOp srcLinalgOp,
                                          LinalgOp dstLinalgOp, Value *view) {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, view,
      {DependenceType::WAW, DependenceType::WAR});
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findCoveringReads(LinalgOp srcLinalgOp,
                                         LinalgOp dstLinalgOp, Value *view) {
  return findOperationsWithCoveringDependences(
      srcLinalgOp, dstLinalgOp, view,
      {DependenceType::RAR, DependenceType::RAW});
}

SmallVector<Operation *, 8>
LinalgDependenceGraph::findOperationsWithCoveringDependences(
    LinalgOp srcLinalgOp, LinalgOp dstLinalgOp, Value *view,
    ArrayRef<DependenceType> types) {
  auto *src = srcLinalgOp.getOperation();
  auto *dst = dstLinalgOp.getOperation();
  auto srcPos = linalgOpPositions[src];
  auto dstPos = linalgOpPositions[dst];
  assert(srcPos < dstPos && "expected dst after src in IR traversal order");

  SmallVector<Operation *, 8> res;
  // Consider an intermediate interleaved `interim` op, look for any dependence
  // to an aliasing view on a src -> op -> dst path.
  // TODO(ntv) we are not considering paths yet, just interleaved positions.
  for (auto dt : types) {
    for (auto dependence : getDependencesFrom(src, dt)) {
      auto interimPos = linalgOpPositions[dependence.dependentOpView.op];
      // Skip if not interleaved.
      if (interimPos >= dstPos || interimPos <= srcPos)
        continue;
      if (view && !aliases.alias(view, dependence.indexingView))
        continue;
      auto *op = dependence.dependentOpView.op;
      LLVM_DEBUG(dbgs() << "\n***Found covering dependence of type " << dt
                        << ": " << *src << " -> " << *op << " on "
                        << *dependence.indexingView);
      res.push_back(op);
    }
  }
  return res;
}
<|endoftext|>


<commit_before>#include <string>
#include <iostream>
#include "cppa/cppa.hpp"

using namespace cppa;

void mirror() {
    // wait for messages
    become (
        // invoke this lambda expression if we receive a string
        on_arg_match >> [](const std::string& what) {
            // prints "Hello World!" via aout (thread-safe wrapper for cout)
            aout << what << std::endl;
            // replies "!dlroW olleH"
            reply(std::string(what.rbegin(), what.rend()));
            // terminates this actor
            self->quit();
        }
    );
}

void hello_world(const actor_ptr& buddy) {
    // send "Hello World!" to our buddy
    send(buddy, "Hello World!");
    // wait for messages
    become (
        on_arg_match >> [](const std::string& what) {
            // prints "!dlroW olleH"
            aout << what << std::endl;
            // terminate this actor
            self->quit();
        }
    );
}

int main() {
    // create a new actor that calls 'mirror()'
    auto mirror_actor = spawn(mirror);
    // create another actor that calls 'hello_world(mirror_actor)'
    spawn(hello_world, mirror_actor);
    // wait until all other actors we have spawned are done
    await_all_others_done();
    // run cleanup code before exiting main
    shutdown();
}
<commit_msg>use sync_send in hello world example<commit_after>#include <string>
#include <iostream>
#include "cppa/cppa.hpp"

using namespace cppa;

void mirror() {
    // wait for messages
    become (
        // invoke this lambda expression if we receive a string
        on_arg_match >> [](const std::string& what) {
            // prints "Hello World!" via aout (thread-safe cout wrapper)
            aout << what << std::endl;
            // replies "!dlroW olleH"
            reply(std::string(what.rbegin(), what.rend()));
            // terminates this actor (become otherwise 'loops' forever)
            self->quit();
        }
    );
}

void hello_world(const actor_ptr& buddy) {
    // send "Hello World!" to our buddy ...
    sync_send(buddy, "Hello World!").then(
        // ... and wait for a response
        on_arg_match >> [](const std::string& what) {
            // prints "!dlroW olleH"
            aout << what << std::endl;
        }
    );
}

int main() {
    // create a new actor that calls 'mirror()'
    auto mirror_actor = spawn(mirror);
    // create another actor that calls 'hello_world(mirror_actor)'
    spawn(hello_world, mirror_actor);
    // wait until all other actors we have spawned are done
    await_all_others_done();
    // run cleanup code before exiting main
    shutdown();
}
<|endoftext|>


<commit_before>// Copyright (C) 2010-2013 Joshua Boyce.
// See the file COPYING for copying permission.

#include <memory>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>

#include <hadesmem/detail/warning_disable_prefix.hpp>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <hadesmem/detail/warning_disable_suffix.hpp>

#include <windows.h>

#include <hadesmem/call.hpp>
#include <hadesmem/error.hpp>
#include <hadesmem/config.hpp>
#include <hadesmem/module.hpp>
#include <hadesmem/process.hpp>
#include <hadesmem/injector.hpp>
#include <hadesmem/detail/self_path.hpp>
#include <hadesmem/detail/initialize.hpp>

// TODO: Add support for for passing args, work dir, etc to CreateAndInject.
// e.g. exe-arg0, exe-arg1, exe-arg2, ..., exe-argN?

namespace
{

std::wstring PtrToString(void const* const ptr)
{
  std::wostringstream str;
  str.imbue(std::locale::classic());
  str << std::hex << reinterpret_cast<DWORD_PTR>(ptr);
  return str.str();
}

}

int main(int argc, char* /*argv*/[])
{
  try
  {
    hadesmem::detail::InitializeAll();

    std::cout << "HadesMem Injector\n";

    boost::program_options::options_description opts_desc(
      "General options");
    opts_desc.add_options()
      ("help", "produce help message")
      ("pid", boost::program_options::value<DWORD>(), "process id")
      ("module", boost::program_options::wvalue<std::wstring>(), "module path")
      ("path-resolution", "perform path resolution")
      ("export", boost::program_options::value<std::string>(), "export name")
      ("free", "unload module")
      ("add-path", "add module dir to serach order")
      ("run", boost::program_options::wvalue<std::wstring>(), "process path")
      ;

    std::vector<std::wstring> const args = boost::program_options::
      split_winmain(GetCommandLine());
    boost::program_options::variables_map var_map;
    boost::program_options::store(boost::program_options::wcommand_line_parser(
      args).options(opts_desc).run(), var_map);
    boost::program_options::notify(var_map);

    if (var_map.count("help") || argc == 1)
    {
      std::cout << '\n' << opts_desc << '\n';
      return 1;
    }

    if (!var_map.count("module"))
    {
      std::cerr << "\nError! Module path must be specified.\n";
      return 1;
    }

    bool const has_pid = (var_map.count("pid") != 0);
    bool const create_proc = (var_map.count("run") != 0);
    if ((has_pid && create_proc) || (!has_pid && !create_proc))
    {
      std::cerr << "\nError! A process ID or an executable path must be "
        "specified.\n";
      return 1;
    }

    bool const inject = (var_map.count("free") == 0);
    if (!inject && create_proc)
    {
      std::cerr << "\nError! Modules can only be unloaded from running "
        "targets.\n";
      return 1;
    }

    std::wstring const module_path = var_map["module"].as<std::wstring>();
    bool const path_resolution = var_map.count("path-resolution") != 0;
    bool const add_path = var_map.count("add-path") != 0;

    int flags = hadesmem::InjectFlags::kNone;
    if (path_resolution)
    {
      flags |= hadesmem::InjectFlags::kPathResolution;
    }
    if (add_path)
    {
      flags |= hadesmem::InjectFlags::kAddToSearchOrder;
    }

    if (has_pid)
    {
      try
      {
        hadesmem::GetSeDebugPrivilege();

        std::wcout << "\nAcquired SeDebugPrivilege.\n";
      }
      catch (std::exception const& /*e*/)
      {
        std::wcout << "\nFailed to acquire SeDebugPrivilege.\n";
      }

      DWORD const pid = var_map["pid"].as<DWORD>();

      hadesmem::Process const process(pid);

      HMODULE module = nullptr;

      if (inject)
      {
        module = hadesmem::InjectDll(process, module_path, flags);

        std::wcout << "\nSuccessfully injected module at base address " <<
          PtrToString(module) << ".\n";
      }
      else
      {
        boost::filesystem::path path_real(module_path);
        if (path_resolution && path_real.is_relative())
        {
          path_real = boost::filesystem::absolute(path_real,
            hadesmem::detail::GetSelfDirPath());
        }
        path_real.make_preferred();

        hadesmem::Module const remote_module(process, path_real.native());
        module = remote_module.GetHandle();
      }

      if (var_map.count("export"))
      {
        std::string const export_name = var_map["export"].as<std::string>();
        auto const export_ret = hadesmem::CallExport(process, module,
          export_name);

        std::wcout << "\nSuccessfully called module export.\n";
        std::wcout << "Return: " << export_ret.GetReturnValue() << ".\n";
        std::wcout << "LastError: " << export_ret.GetLastError() << ".\n";
      }

      if (!inject)
      {
        hadesmem::FreeDll(process, module);

        std::wcout << "\nSuccessfully freed module at base address " <<
          PtrToString(module) << ".\n";
      }
    }
    else
    {
      std::vector<std::wstring> args;
      std::wstring const exe_path = var_map["run"].as<std::wstring>();
      std::string const export_name = var_map.count("export") ?
        var_map["export"].as<std::string>() : "";
      hadesmem::CreateAndInjectData const inject_data =
        hadesmem::CreateAndInject(
        exe_path,
        L"",
        std::begin(args),
        std::end(args),
        module_path,
        export_name,
        flags);

      std::wcout << "\nSuccessfully created target.\n";
      std::wcout << "Process ID: " << inject_data.GetProcess() << ".\n";
      std::wcout << "Module Base: " << PtrToString(inject_data.GetModule())
        << ".\n";
      std::wcout << "Export Return: " << inject_data.GetExportRet() << ".\n";
      std::wcout << "Export LastError: " << inject_data.GetExportLastError()
        << ".\n";
    }

    return 0;
  }
  catch (std::exception const& e)
  {
    std::cerr << "\nError!\n";
    std::cerr << boost::diagnostic_information(e) << '\n';

    return 1;
  }
}
<commit_msg>* Fix warning.<commit_after>// Copyright (C) 2010-2013 Joshua Boyce.
// See the file COPYING for copying permission.

#include <memory>
#include <string>
#include <vector>
#include <sstream>
#include <iostream>

#include <hadesmem/detail/warning_disable_prefix.hpp>
#include <boost/filesystem.hpp>
#include <boost/program_options.hpp>
#include <hadesmem/detail/warning_disable_suffix.hpp>

#include <windows.h>

#include <hadesmem/call.hpp>
#include <hadesmem/error.hpp>
#include <hadesmem/config.hpp>
#include <hadesmem/module.hpp>
#include <hadesmem/process.hpp>
#include <hadesmem/injector.hpp>
#include <hadesmem/detail/self_path.hpp>
#include <hadesmem/detail/initialize.hpp>

// TODO: Add support for for passing args, work dir, etc to CreateAndInject.
// e.g. exe-arg0, exe-arg1, exe-arg2, ..., exe-argN?

namespace
{

std::wstring PtrToString(void const* const ptr)
{
  std::wostringstream str;
  str.imbue(std::locale::classic());
  str << std::hex << reinterpret_cast<DWORD_PTR>(ptr);
  return str.str();
}

}

int main(int argc, char* /*argv*/[])
{
  try
  {
    hadesmem::detail::InitializeAll();

    std::cout << "HadesMem Injector\n";

    boost::program_options::options_description opts_desc(
      "General options");
    opts_desc.add_options()
      ("help", "produce help message")
      ("pid", boost::program_options::value<DWORD>(), "process id")
      ("module", boost::program_options::wvalue<std::wstring>(), "module path")
      ("path-resolution", "perform path resolution")
      ("export", boost::program_options::value<std::string>(), "export name")
      ("free", "unload module")
      ("add-path", "add module dir to serach order")
      ("run", boost::program_options::wvalue<std::wstring>(), "process path")
      ;

    std::vector<std::wstring> const args = boost::program_options::
      split_winmain(GetCommandLine());
    boost::program_options::variables_map var_map;
    boost::program_options::store(boost::program_options::wcommand_line_parser(
      args).options(opts_desc).run(), var_map);
    boost::program_options::notify(var_map);

    if (var_map.count("help") || argc == 1)
    {
      std::cout << '\n' << opts_desc << '\n';
      return 1;
    }

    if (!var_map.count("module"))
    {
      std::cerr << "\nError! Module path must be specified.\n";
      return 1;
    }

    bool const has_pid = (var_map.count("pid") != 0);
    bool const create_proc = (var_map.count("run") != 0);
    if ((has_pid && create_proc) || (!has_pid && !create_proc))
    {
      std::cerr << "\nError! A process ID or an executable path must be "
        "specified.\n";
      return 1;
    }

    bool const inject = (var_map.count("free") == 0);
    if (!inject && create_proc)
    {
      std::cerr << "\nError! Modules can only be unloaded from running "
        "targets.\n";
      return 1;
    }

    std::wstring const module_path = var_map["module"].as<std::wstring>();
    bool const path_resolution = var_map.count("path-resolution") != 0;
    bool const add_path = var_map.count("add-path") != 0;

    int flags = hadesmem::InjectFlags::kNone;
    if (path_resolution)
    {
      flags |= hadesmem::InjectFlags::kPathResolution;
    }
    if (add_path)
    {
      flags |= hadesmem::InjectFlags::kAddToSearchOrder;
    }

    if (has_pid)
    {
      try
      {
        hadesmem::GetSeDebugPrivilege();

        std::wcout << "\nAcquired SeDebugPrivilege.\n";
      }
      catch (std::exception const& /*e*/)
      {
        std::wcout << "\nFailed to acquire SeDebugPrivilege.\n";
      }

      DWORD const pid = var_map["pid"].as<DWORD>();

      hadesmem::Process const process(pid);

      HMODULE module = nullptr;

      if (inject)
      {
        module = hadesmem::InjectDll(process, module_path, flags);

        std::wcout << "\nSuccessfully injected module at base address " <<
          PtrToString(module) << ".\n";
      }
      else
      {
        boost::filesystem::path path_real(module_path);
        if (path_resolution && path_real.is_relative())
        {
          path_real = boost::filesystem::absolute(path_real,
            hadesmem::detail::GetSelfDirPath());
        }
        path_real.make_preferred();

        hadesmem::Module const remote_module(process, path_real.native());
        module = remote_module.GetHandle();
      }

      if (var_map.count("export"))
      {
        std::string const export_name = var_map["export"].as<std::string>();
        auto const export_ret = hadesmem::CallExport(process, module,
          export_name);

        std::wcout << "\nSuccessfully called module export.\n";
        std::wcout << "Return: " << export_ret.GetReturnValue() << ".\n";
        std::wcout << "LastError: " << export_ret.GetLastError() << ".\n";
      }

      if (!inject)
      {
        hadesmem::FreeDll(process, module);

        std::wcout << "\nSuccessfully freed module at base address " <<
          PtrToString(module) << ".\n";
      }
    }
    else
    {
      std::vector<std::wstring> create_args;
      std::wstring const exe_path = var_map["run"].as<std::wstring>();
      std::string const export_name = var_map.count("export") ?
        var_map["export"].as<std::string>() : "";
      hadesmem::CreateAndInjectData const inject_data =
        hadesmem::CreateAndInject(
        exe_path,
        L"",
        std::begin(create_args),
        std::end(create_args),
        module_path,
        export_name,
        flags);

      std::wcout << "\nSuccessfully created target.\n";
      std::wcout << "Process ID: " << inject_data.GetProcess() << ".\n";
      std::wcout << "Module Base: " << PtrToString(inject_data.GetModule())
        << ".\n";
      std::wcout << "Export Return: " << inject_data.GetExportRet() << ".\n";
      std::wcout << "Export LastError: " << inject_data.GetExportLastError()
        << ".\n";
    }

    return 0;
  }
  catch (std::exception const& e)
  {
    std::cerr << "\nError!\n";
    std::cerr << boost::diagnostic_information(e) << '\n';

    return 1;
  }
}
<|endoftext|>