<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2010 Hermann Kraus
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// Mapnik
#include <mapnik/metawriter.hpp>
#include <mapnik/metawriter_json.hpp>
#include <mapnik/placement_finder.hpp>

// Boost
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>

// STL
#include <iomanip>
#include <cstdio>

namespace mapnik {

UnicodeString const& metawriter_property_map::operator[](std::string const& key) const
{
    std::map<std::string, UnicodeString>::const_iterator it;
    it = m_.find(key);
    if (it == m_.end()) return not_found_;
    return (*it).second;
}

metawriter_properties::metawriter_properties(boost::optional<std::string> str)
{
    if (str) {
        boost::split(*this, *str, boost::is_any_of(", "), boost::token_compress_on);
    }
}

/********************************************************************************************/

void metawriter_json_stream::start(metawriter_property_map const& properties)
{
    assert(trans_);
    if (!only_nonempty_) {
        write_header();
    } else {
        count_ = HEADER_NOT_WRITTEN;
    }
}

void metawriter_json_stream::write_header()
{
    assert(f_);
    *f_ << "{ \"type\": \"FeatureCollection\", \"features\": [\n" << std::fixed << std::setprecision(8);
    count_ = STARTED;
}

void metawriter_json_stream::stop()
{
    if (count_ >= STARTED && f_) {
        *f_ << " ] }\n";
    }
    count_ = STOPPED;
}

metawriter_json_stream::~metawriter_json_stream()
{
    if (count_ >= STARTED) {
#ifdef MAPNIK_DEBUG
        std::cerr << "WARNING: GeoJSON metawriter not stopped before destroying it.";
#endif
        stop();
    }
    if (trans_) delete trans_;
}

metawriter_json_stream::metawriter_json_stream(metawriter_properties dflt_properties)
    : metawriter(dflt_properties), count_(-1), only_nonempty_(true),
      trans_(0), output_srs_("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"), f_(0)
{
}

void metawriter_json_stream::write_properties(Feature const& feature, metawriter_properties const& properties)
{
    *f_ << "}," << //Close coordinates object
            "\n  \"properties\": {";
    std::map<std::string, value> fprops = feature.props();
    int i = 0;
    BOOST_FOREACH(std::string p, properties)
    {
        std::map<std::string, value>::const_iterator itr = fprops.find(p);
        std::string text;
        if (itr != fprops.end())
        {
            //Property found
            text = boost::replace_all_copy(boost::replace_all_copy(itr->second.to_string(), "\\", "\\\\"), "\"", "\\\"");
        }
        if (i++) *f_ << ",";
        *f_ << "\n    \"" << p << "\":\"" << text << "\"";
    }

    *f_ << "\n} }";
}

/* Coordinate transform in renderer:
   input: layer srs
   prj_trans.backwards()   [prj_trans: map -> layer]
   intermediate: map srs
   t_.forward()
   output: pixels

   Our transform:
   input: pixels
   t_.backward()
   intermediate: map srs
   trans_.forward()
   output: WGS84
*/

void metawriter_json_stream::add_box(box2d<double> const &box, Feature const& feature,
                              CoordTransform const& t, metawriter_properties const& properties)
{
    /* Check if feature is in bounds. */
    if (box.maxx() < 0 || box.maxy() < 0 || box.minx() > width_ || box.miny() > height_) return;

    //t_ coord transform has transform for box2d combined with proj_transform
    box2d<double> transformed = t.backward(box, *trans_);

    double minx = transformed.minx();
    double miny = transformed.miny();
    double maxx = transformed.maxx();
    double maxy = transformed.maxy();

    write_feature_header("Polygon");

    *f_ << " [ [ [" <<
            minx << ", " << miny << "], [" <<
            maxx << ", " << miny << "], [" <<
            maxx << ", " << maxy << "], [" <<
            minx << ", " << maxy << "] ] ]";

    write_properties(feature, properties);

}

void metawriter_json_stream::add_text(placement const& p,
    face_set_ptr face,
    Feature const& feature,
    CoordTransform const& t,
    metawriter_properties const& properties)
{
    for (unsigned n = 0; n < p.placements.size(); n++) {
        placement_element & current_placement = const_cast<placement_element &>(p.placements[n]);

        bool inside = false;
        for (int i = 0; i < current_placement.num_nodes(); ++i) {
            current_placement.rewind();
            int cx = current_placement.starting_x;
            int cy = current_placement.starting_y;
            int c; double x, y, angle;
            current_placement.vertex(&c, &x, &y, &angle);
            if (x+cx >= 0 && x+cx < width_ && y+cy >= 0 && y+cy < height_) {
                inside = true;
                break;
            }
        }
        if (!inside) continue;

        write_feature_header("MultiPolygon");
        *f_ << "[";
        current_placement.rewind();

        int c = ' ';
        for (int i = 0; i < current_placement.num_nodes(); ++i) {
            if (c != ' ') {
                *f_ << ",";
            }
            double x, y, angle;
            current_placement.vertex(&c, &x, &y, &angle);
            if (c == ' ') continue;
            font_face_set::dimension_t ci = face->character_dimensions(c);

            //TODO: Optimize for angle == 0
            double x0, y0, x1, y1, x2, y2, x3, y3;
            if (abs(angle) > 0.01) {
                double sina = sin(angle);
                double cosa = cos(angle);
                x0 = current_placement.starting_x + x - sina*ci.ymin;
                y0 = current_placement.starting_y - y - cosa*ci.ymin;
                x1 = x0 + ci.width * cosa;
                y1 = y0 - ci.width * sina;
                x2 = x0 + (ci.width * cosa - ci.height * sina);
                y2 = y0 - (ci.width * sina + ci.height * cosa);
                x3 = x0 - ci.height * sina;
                y3 = y0 - ci.height * cosa;
            } else {
                x0 = current_placement.starting_x + x;
                y0 = current_placement.starting_y - y - ci.ymin;
                x1 = x0 + ci.width;
                y1 = y0;
                x2 = x0 + ci.width;
                y2 = y0 - ci.height;
                x3 = x0;
                y3 = y0 - ci.height;
            }

            *f_ << "\n     [[";
            write_point(t, x0, y0);
            write_point(t, x1, y1);
            write_point(t, x2, y2);
            write_point(t, x3, y3, true);
            *f_ << "]]";
        }
        *f_ << "]";
        write_properties(feature, properties);
    }
}

void metawriter_json_stream::set_map_srs(projection const& input_srs_)
{
    if (trans_) delete trans_;
    trans_ = new proj_transform(input_srs_, output_srs_);
}

/********************************************************************************************/

metawriter_json::metawriter_json(metawriter_properties dflt_properties, path_expression_ptr fn)
    : metawriter_json_stream(dflt_properties), fn_(fn) {}

void metawriter_json::start(metawriter_property_map const& properties)
{
    filename_ =
        path_processor<metawriter_property_map>::evaluate(*fn_, properties);
#ifdef MAPNIK_DEBUG
    std::clog << "Metawriter JSON: filename=" << filename_ << "\n";
#endif
    metawriter_json_stream::start(properties);
}

void metawriter_json::write_header()
{
    f_.open(filename_.c_str(), std::fstream::out | std::fstream::trunc);
    if (f_.fail()) perror((std::string("Metawriter JSON: Failed to open file ") + filename_).c_str());
    set_stream(&f_);
    metawriter_json_stream::write_header();
}

void metawriter_json::stop()
{
    metawriter_json_stream::stop();
    if (f_.is_open()) {
        f_.close();
    }
#ifdef MAPNIK_DEBUG
    else {
        std::clog << "WARNING: File not open in metawriter_json::stop()!\n";
    }
#endif
}

void metawriter_json::set_filename(path_expression_ptr fn)
{
    fn_ = fn;
}

 path_expression_ptr metawriter_json::get_filename() const
 {
     return fn_;
 }

};
<commit_msg>Handle straight lines specially. Add comment about coordinate systems.<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2010 Hermann Kraus
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

// Mapnik
#include <mapnik/metawriter.hpp>
#include <mapnik/metawriter_json.hpp>
#include <mapnik/placement_finder.hpp>

// Boost
#include <boost/foreach.hpp>
#include <boost/algorithm/string.hpp>

// STL
#include <iomanip>
#include <cstdio>

namespace mapnik {

UnicodeString const& metawriter_property_map::operator[](std::string const& key) const
{
    std::map<std::string, UnicodeString>::const_iterator it;
    it = m_.find(key);
    if (it == m_.end()) return not_found_;
    return (*it).second;
}

metawriter_properties::metawriter_properties(boost::optional<std::string> str)
{
    if (str) {
        boost::split(*this, *str, boost::is_any_of(", "), boost::token_compress_on);
    }
}

/********************************************************************************************/

void metawriter_json_stream::start(metawriter_property_map const& properties)
{
    assert(trans_);
    if (!only_nonempty_) {
        write_header();
    } else {
        count_ = HEADER_NOT_WRITTEN;
    }
}

void metawriter_json_stream::write_header()
{
    assert(f_);
    *f_ << "{ \"type\": \"FeatureCollection\", \"features\": [\n" << std::fixed << std::setprecision(8);
    count_ = STARTED;
}

void metawriter_json_stream::stop()
{
    if (count_ >= STARTED && f_) {
        *f_ << " ] }\n";
    }
    count_ = STOPPED;
}

metawriter_json_stream::~metawriter_json_stream()
{
    if (count_ >= STARTED) {
#ifdef MAPNIK_DEBUG
        std::cerr << "WARNING: GeoJSON metawriter not stopped before destroying it.";
#endif
        stop();
    }
    if (trans_) delete trans_;
}

metawriter_json_stream::metawriter_json_stream(metawriter_properties dflt_properties)
    : metawriter(dflt_properties), count_(-1), only_nonempty_(true),
      trans_(0), output_srs_("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"), f_(0)
{
}

void metawriter_json_stream::write_properties(Feature const& feature, metawriter_properties const& properties)
{
    *f_ << "}," << //Close coordinates object
            "\n  \"properties\": {";
    std::map<std::string, value> fprops = feature.props();
    int i = 0;
    BOOST_FOREACH(std::string p, properties)
    {
        std::map<std::string, value>::const_iterator itr = fprops.find(p);
        std::string text;
        if (itr != fprops.end())
        {
            //Property found
            text = boost::replace_all_copy(boost::replace_all_copy(itr->second.to_string(), "\\", "\\\\"), "\"", "\\\"");
        }
        if (i++) *f_ << ",";
        *f_ << "\n    \"" << p << "\":\"" << text << "\"";
    }

    *f_ << "\n} }";
}

/* Coordinate transform in renderer:
   input: layer srs
   prj_trans.backwards()   [prj_trans: map -> layer]
   intermediate: map srs
   t_.forward()
   output: pixels

   Our transform:
   input: pixels
   t_.backward()
   intermediate: map srs
   trans_.forward()
   output: WGS84
*/

void metawriter_json_stream::add_box(box2d<double> const &box, Feature const& feature,
                              CoordTransform const& t, metawriter_properties const& properties)
{
    /* Check if feature is in bounds. */
    if (box.maxx() < 0 || box.maxy() < 0 || box.minx() > width_ || box.miny() > height_) return;

    //t_ coord transform has transform for box2d combined with proj_transform
    box2d<double> transformed = t.backward(box, *trans_);

    double minx = transformed.minx();
    double miny = transformed.miny();
    double maxx = transformed.maxx();
    double maxy = transformed.maxy();

    write_feature_header("Polygon");

    *f_ << " [ [ [" <<
            minx << ", " << miny << "], [" <<
            maxx << ", " << miny << "], [" <<
            maxx << ", " << maxy << "], [" <<
            minx << ", " << maxy << "] ] ]";

    write_properties(feature, properties);

}

void metawriter_json_stream::add_text(placement const& p,
    face_set_ptr face,
    Feature const& feature,
    CoordTransform const& t,
    metawriter_properties const& properties)
{
    /* Note:
       Map coordinate system (and starting_{x,y}) starts in upper left corner
         and grows towards lower right corner.
       Font + placement vertex coordinate system starts in lower left corner
         and grows towards upper right corner.
       Therefore y direction is different. Keep this in mind while doing calculations.

       The y value returned by vertex() is always the baseline.
       Lowest y = baseline of bottom line
       Hightest y = baseline of top line

      */
//    if (p.placements.size()) std::cout << p.info.get_string() << "\n";
    for (unsigned n = 0; n < p.placements.size(); n++) {
        placement_element & current_placement = const_cast<placement_element &>(p.placements[n]);

        bool inside = false;
        bool straight = true;
        int c; double x, y, angle;
        for (int i = 0; i < current_placement.num_nodes(); ++i) {
            current_placement.rewind();
            int cx = current_placement.starting_x;
            int cy = current_placement.starting_y;
            current_placement.vertex(&c, &x, &y, &angle);
            if (x+cx >= 0 && x+cx < width_ && y+cy >= 0 && y+cy < height_) inside = true;
            if (angle > 0.001 || angle < -0.001) straight = false;
            if (inside && !straight) break;
        }
        if (!inside) continue;

        current_placement.rewind();

        if (straight) {
            //Reduce number of polygons
            double minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN;
            for (int i = 0; i < current_placement.num_nodes(); ++i) {
                current_placement.vertex(&c, &x, &y, &angle);
                font_face_set::dimension_t ci = face->character_dimensions(c);
                if (x < minx) minx = x;
                if (x+ci.width > maxx) maxx = x+ci.width;
                if (y+ci.height+ci.ymin > maxy) maxy = y+ci.height+ci.ymin;
                if (y+ci.ymin < miny) miny = y+ci.ymin;
                //                std::cout << (char) c << " height:" << ci.height << " ymin:" << ci.ymin << " y:" << y << " miny:"<< miny << " maxy:"<< maxy <<"\n";

            }
            add_box(box2d<double>(current_placement.starting_x+minx,
                                  current_placement.starting_y-miny,
                                  current_placement.starting_x+maxx,
                                  current_placement.starting_y-maxy), feature, t, properties);
            continue;
        }

        write_feature_header("MultiPolygon");
        *f_ << "[";
        c = ' ';
        for (int i = 0; i < current_placement.num_nodes(); ++i) {
            if (c != ' ') {
                *f_ << ",";
            }
            current_placement.vertex(&c, &x, &y, &angle);
            if (c == ' ') continue;
            font_face_set::dimension_t ci = face->character_dimensions(c);

            double x0, y0, x1, y1, x2, y2, x3, y3;
            double sina = sin(angle);
            double cosa = cos(angle);
            x0 = current_placement.starting_x + x - sina*ci.ymin;
            y0 = current_placement.starting_y - y - cosa*ci.ymin;
            x1 = x0 + ci.width * cosa;
            y1 = y0 - ci.width * sina;
            x2 = x0 + (ci.width * cosa - ci.height * sina);
            y2 = y0 - (ci.width * sina + ci.height * cosa);
            x3 = x0 - ci.height * sina;
            y3 = y0 - ci.height * cosa;

            *f_ << "\n     [[";
            write_point(t, x0, y0);
            write_point(t, x1, y1);
            write_point(t, x2, y2);
            write_point(t, x3, y3, true);
            *f_ << "]]";
        }
        *f_ << "]";
        write_properties(feature, properties);
    }
}

void metawriter_json_stream::set_map_srs(projection const& input_srs_)
{
    if (trans_) delete trans_;
    trans_ = new proj_transform(input_srs_, output_srs_);
}

/********************************************************************************************/

metawriter_json::metawriter_json(metawriter_properties dflt_properties, path_expression_ptr fn)
    : metawriter_json_stream(dflt_properties), fn_(fn) {}

void metawriter_json::start(metawriter_property_map const& properties)
{
    filename_ =
        path_processor<metawriter_property_map>::evaluate(*fn_, properties);
#ifdef MAPNIK_DEBUG
    std::clog << "Metawriter JSON: filename=" << filename_ << "\n";
#endif
    metawriter_json_stream::start(properties);
}

void metawriter_json::write_header()
{
    f_.open(filename_.c_str(), std::fstream::out | std::fstream::trunc);
    if (f_.fail()) perror((std::string("Metawriter JSON: Failed to open file ") + filename_).c_str());
    set_stream(&f_);
    metawriter_json_stream::write_header();
}

void metawriter_json::stop()
{
    metawriter_json_stream::stop();
    if (f_.is_open()) {
        f_.close();
    }
#ifdef MAPNIK_DEBUG
    else {
        std::clog << "WARNING: File not open in metawriter_json::stop()!\n";
    }
#endif
}

void metawriter_json::set_filename(path_expression_ptr fn)
{
    fn_ = fn;
}

 path_expression_ptr metawriter_json::get_filename() const
 {
     return fn_;
 }

};
<|endoftext|>


<commit_before>//
//  fiberize.cpp
//  fibio
//
//  Created by Chen Xu on 14-3-10.
//  Copyright (c) 2014 0d0a.com. All rights reserved.
//

#include <fibio/fibers/fiberize.hpp>
//#include "std_stream_guard.hpp"

namespace fibio { namespace fibers { namespace detail {
    fiberized_std_stream_guard::fiberized_std_stream_guard(asio::io_service &iosvc)
    : old_cin_buf_(0)
    , old_cout_buf_(0)
    , old_cerr_buf_(0)
    , cin_buf_(new sbuf_t())
    , cout_buf_(new sbuf_t())
    , cerr_buf_(new sbuf_t())
    {
        old_cin_buf_=std::cin.rdbuf(cin_buf_);
        old_cout_buf_=std::cout.rdbuf(cout_buf_);
        old_cerr_buf_=std::cerr.rdbuf(cerr_buf_);
        cin_buf_->assign(0);
        cout_buf_->assign(1);
        cerr_buf_->assign(2);
        // Set cerr to unbuffered
        std::cerr.rdbuf()->pubsetbuf(0, 0);
    }

    fiberized_std_stream_guard::~fiberized_std_stream_guard() {
        std::cout.flush();
        std::cerr.flush();
        cin_buf_->release();
        cout_buf_->release();
        cerr_buf_->release();
        std::cin.rdbuf(old_cin_buf_);
        std::cout.rdbuf(old_cout_buf_);
        std::cerr.rdbuf(old_cerr_buf_);
        delete cin_buf_;
        delete cout_buf_;
        delete cerr_buf_;
    }

    void fiberized_std_stream_guard::open() {
        if (cin_buf_->is_open()) {
            return;
        }
        cin_buf_->assign(0);
        cout_buf_->assign(1);
        cerr_buf_->assign(2);
        // Set cerr to unbuffered
        std::cerr.rdbuf()->pubsetbuf(0, 0);
    }
}}}   // End of namespace fibio::fibers::detail
<commit_msg>remove unused header<commit_after>//
//  fiberize.cpp
//  fibio
//
//  Created by Chen Xu on 14-3-10.
//  Copyright (c) 2014 0d0a.com. All rights reserved.
//

#include <fibio/fibers/fiberize.hpp>

namespace fibio { namespace fibers { namespace detail {
    fiberized_std_stream_guard::fiberized_std_stream_guard(asio::io_service &iosvc)
    : old_cin_buf_(0)
    , old_cout_buf_(0)
    , old_cerr_buf_(0)
    , cin_buf_(new sbuf_t())
    , cout_buf_(new sbuf_t())
    , cerr_buf_(new sbuf_t())
    {
        old_cin_buf_=std::cin.rdbuf(cin_buf_);
        old_cout_buf_=std::cout.rdbuf(cout_buf_);
        old_cerr_buf_=std::cerr.rdbuf(cerr_buf_);
        cin_buf_->assign(0);
        cout_buf_->assign(1);
        cerr_buf_->assign(2);
        // Set cerr to unbuffered
        std::cerr.rdbuf()->pubsetbuf(0, 0);
    }

    fiberized_std_stream_guard::~fiberized_std_stream_guard() {
        std::cout.flush();
        std::cerr.flush();
        cin_buf_->release();
        cout_buf_->release();
        cerr_buf_->release();
        std::cin.rdbuf(old_cin_buf_);
        std::cout.rdbuf(old_cout_buf_);
        std::cerr.rdbuf(old_cerr_buf_);
        delete cin_buf_;
        delete cout_buf_;
        delete cerr_buf_;
    }

    void fiberized_std_stream_guard::open() {
        if (cin_buf_->is_open()) {
            return;
        }
        cin_buf_->assign(0);
        cout_buf_->assign(1);
        cerr_buf_->assign(2);
        // Set cerr to unbuffered
        std::cerr.rdbuf()->pubsetbuf(0, 0);
    }
}}}   // End of namespace fibio::fibers::detail
<|endoftext|>


<commit_before>/*
    Copyright (C) 2003 by Jorrit Tyberghein
              (C) 2003 by Frank Richter

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"

#include "csutil/scf.h"
#include "csgfx/packrgb.h"
#include "csplugincommon/opengl/glcommon2d.h"
#include "csplugincommon/opengl/glss.h"

void csGLScreenShot::IncRef ()
{
  scfRefCount++;
}

void csGLScreenShot::DecRef()
{
  if (scfRefCount == 1)
  {
    G2D->RecycleScreenShot (this);
    return;
  }
  scfRefCount--;
}

SCF_IMPLEMENT_IBASE_GETREFCOUNT(csGLScreenShot)
SCF_IMPLEMENT_IBASE_REFOWNER(csGLScreenShot)
SCF_IMPLEMENT_IBASE_REMOVE_REF_OWNERS(csGLScreenShot)
SCF_IMPLEMENT_IBASE_QUERY(csGLScreenShot)
  SCF_IMPLEMENTS_INTERFACE(iImage)
SCF_IMPLEMENT_IBASE_END

csGLScreenShot::csGLScreenShot (csGraphics2DGLCommon* G2D)
{
  SCF_CONSTRUCT_IBASE(0);

  poolNext = 0;
  csGLScreenShot::G2D = G2D;
  Format = CS_IMGFMT_TRUECOLOR | CS_IMGFMT_ALPHA;
  Data = 0;
  dataSize = 0;
}

csGLScreenShot::~csGLScreenShot ()
{
  delete[] Data;
  SCF_DESTRUCT_IBASE();
}

void csGLScreenShot::SetData (void* data)
{
  Width = G2D->GetWidth ();
  Height = G2D->GetHeight ();
  if (dataSize < (size_t)(Width * Height))
  {
    delete[] Data;
    Data = new csRGBpixel [Width * Height];
    dataSize = Width * Height;
  }

  // Pixel format is read as RGBA (in a byte array)
  uint8* s = (uint8*)data;
  int y;
  for (y = Height; y-- > 0;)
  {
    csRGBpixel* dest = Data + y * Width;
    csPackRGBA::UnpackRGBAtoRGBpixel (dest, s, Width);
    s += Width*4;
  }
}

<commit_msg>Revert CS_IMGFMT_ALPHA addition for GL screen shot images. While useful for debugging, it isn't for normal SS usage.<commit_after>/*
    Copyright (C) 2003 by Jorrit Tyberghein
              (C) 2003 by Frank Richter

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Library General Public
    License as published by the Free Software Foundation; either
    version 2 of the License, or (at your option) any later version.

    This library 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
    Library General Public License for more details.

    You should have received a copy of the GNU Library General Public
    License along with this library; if not, write to the Free
    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "cssysdef.h"

#include "csutil/scf.h"
#include "csgfx/packrgb.h"
#include "csplugincommon/opengl/glcommon2d.h"
#include "csplugincommon/opengl/glss.h"

void csGLScreenShot::IncRef ()
{
  scfRefCount++;
}

void csGLScreenShot::DecRef()
{
  if (scfRefCount == 1)
  {
    G2D->RecycleScreenShot (this);
    return;
  }
  scfRefCount--;
}

SCF_IMPLEMENT_IBASE_GETREFCOUNT(csGLScreenShot)
SCF_IMPLEMENT_IBASE_REFOWNER(csGLScreenShot)
SCF_IMPLEMENT_IBASE_REMOVE_REF_OWNERS(csGLScreenShot)
SCF_IMPLEMENT_IBASE_QUERY(csGLScreenShot)
  SCF_IMPLEMENTS_INTERFACE(iImage)
SCF_IMPLEMENT_IBASE_END

csGLScreenShot::csGLScreenShot (csGraphics2DGLCommon* G2D)
{
  SCF_CONSTRUCT_IBASE(0);

  poolNext = 0;
  csGLScreenShot::G2D = G2D;
  /* @@@ FIXME:
   * For debugging, it would be nice to also store the alpha channel in the
   * screenshot. However, for "normal" screenshot usage, this would be
   * undesireable, since the alpha channel values would go into the screenshot
   * written to disk, causing areas of it to unexpectedly appear transparent.
   */
  Format = CS_IMGFMT_TRUECOLOR /*| CS_IMGFMT_ALPHA*/;
  Data = 0;
  dataSize = 0;
}

csGLScreenShot::~csGLScreenShot ()
{
  delete[] Data;
  SCF_DESTRUCT_IBASE();
}

void csGLScreenShot::SetData (void* data)
{
  Width = G2D->GetWidth ();
  Height = G2D->GetHeight ();
  if (dataSize < (size_t)(Width * Height))
  {
    delete[] Data;
    Data = new csRGBpixel [Width * Height];
    dataSize = Width * Height;
  }

  // Pixel format is read as RGBA (in a byte array)
  uint8* s = (uint8*)data;
  int y;
  for (y = Height; y-- > 0;)
  {
    csRGBpixel* dest = Data + y * Width;
    csPackRGBA::UnpackRGBAtoRGBpixel (dest, s, Width);
    s += Width*4;
  }
}

<|endoftext|>


<commit_before>/*****************************************************************************
 * Copyright (C) 2011-2013 Michael Krufky
 *
 * Author: Michael Krufky <mkrufky@linuxtv.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <map>

#include "tune.h"
#include "log.h"
#define CLASS_MODULE "tune"

#define dprintf(fmt, arg...) __dprintf(DBG_TUNE, fmt, ##arg)

typedef std::map<unsigned int, uint16_t> map_chan_to_ts_id;

static map_chan_to_ts_id channels;

tune::tune()
  : h_thread((pthread_t)NULL)
  , f_kill_thread(false)
  , state(TUNE_STATE_IDLE)
  , cur_chan(0)
  , time_touched((time_t)0)
  , scan_mode(0)
  , scan_epg(false)
  , scan_complete(false)
  , fe_type(DVBTEE_FE_OFDM)
  , last_query((time_t)0)
  , scan_progress_cb(NULL)
  , scan_progress_context(NULL)
{
	dprintf("()");
//	channels.clear();
}

tune::~tune()
{
	dprintf("()");
	stop_feed();
	close_fe();
//	channels.clear();
}

tune::tune(const tune&)
{
	dprintf("(copy)");

//	channels.clear();
	feeder.parser.cleanup();
	h_thread = (pthread_t)NULL;
	f_kill_thread = false;
	cur_chan = 0;
	state = TUNE_STATE_IDLE;
	time_touched = (time_t)0;
	scan_mode = 0;
	scan_epg = false;
	scan_complete = false;
	fe_type = DVBTEE_FE_OFDM;
	last_query = (time_t)0;
	scan_progress_cb = NULL;
	scan_progress_context = NULL;
}

tune& tune::operator= (const tune& cSource)
{
	dprintf("(operator=)");

	if (this == &cSource)
		return *this;

//	channels.clear();
	feeder.parser.cleanup();
	h_thread = (pthread_t)NULL;
	f_kill_thread = false;
	cur_chan = 0;
	state = TUNE_STATE_IDLE;
	time_touched = (time_t)0;
	scan_mode = 0;
	scan_epg = false;
	scan_complete = false;
	fe_type = DVBTEE_FE_OFDM;
	last_query = (time_t)0;
	scan_progress_cb = NULL;
	scan_progress_context = NULL;

	return *this;
}

int tune::close_fe() {
	cur_chan = 0;
	state &= ~TUNE_STATE_OPEN;
	state &= ~TUNE_STATE_LOCK;
	return 0;
}

bool tune::wait_for_lock_or_timeout(unsigned int time_ms)
{
	unsigned int status = (dvbtee_fe_status_t)0;
	time_t start_time = time(NULL);
	while ((0 == ((status |= fe_status()) & DVBTEE_FE_HAS_LOCK)) && ( (time(NULL) - start_time) < ((int)time_ms / 1000) ))
		usleep(200*1000);
	if ((status & (DVBTEE_FE_HAS_LOCK | DVBTEE_FE_HAS_SYNC)) == DVBTEE_FE_HAS_SYNC) {
		start_time = time(NULL);
		while ((0 == ((status |= fe_status()) & DVBTEE_FE_HAS_LOCK)) && ( (time(NULL) - start_time) < (2 * (int)time_ms / 1000) ))
			usleep(200*1000);
	}
	return ((status & DVBTEE_FE_HAS_LOCK) == DVBTEE_FE_HAS_LOCK);
}

bool tune::tune_channel(dvbtee_fe_modulation_t modulation, unsigned int channel)
{
	feeder.parser.reset();

	return __tune_channel(modulation, channel);
}

void tune::stop_feed()
{
	feeder.stop();
	state &= ~TUNE_STATE_FEED;
	feeder.close_file();
}

time_t tune::last_touched() // sec_ago
{
	time_t timenow;
	time(&timenow);
	time_t ret = timenow - time_touched;
	if (timenow - last_query)
		dprintf("last touched %ld seconds ago", ret);
	time(&last_query);
	return ret;
}

//static
void* tune::scan_thread(void *p_this)
{
	return static_cast<tune*>(p_this)->scan_thread();
}

void* tune::scan_thread()
{
	if (!is_scan()) {

	scan_progress_t progress;

	progress.total = (unsigned int)scan_channel_list.size(),
	progress.current = 0,
	progress.physical_channel = 0,

	state |= TUNE_STATE_SCAN;

	feeder.parser.set_scan_mode(true);
	feeder.parser.set_epg_mode(scan_epg);

	for (channel_map::const_iterator iter = scan_channel_list.begin(); iter != scan_channel_list.end(); ++iter) {
		unsigned int channel = iter->first;
		progress.current++;
		progress.physical_channel = channel;

		if (f_kill_thread)
			break;
#if 0
		map_chan_to_ts_id::const_iterator iter = channels.find(channel);
		if (iter != channels.end()) {
#else
		if (channels.count(channel)) {
#endif
			fprintf(stderr, "ALREADY SCANNED CHANNEL %d\n", channel);
			continue;
		}

		fprintf(stderr, "scan channel %d...\n", channel);

		if (scan_progress_cb)
			scan_progress_cb(scan_progress_context, &progress);

		if ((!f_kill_thread) && ((tune_channel((scan_mode == SCAN_VSB) ? DVBTEE_VSB_8 : DVBTEE_QAM_256, channel)) && (wait_for_lock_or_timeout(2000)))) {

			if (f_kill_thread)
				break;

			switch (fe_type) {
			default:
			case DVBTEE_FE_ATSC:
				feeder.parser.set_channel_info(channel,
							       (scan_mode == SCAN_VSB) ? atsc_vsb_chan_to_freq(channel) : atsc_qam_chan_to_freq(channel),
							       (scan_mode == SCAN_VSB) ? "8VSB" : "QAM_256");
				break;
			case DVBTEE_FE_OFDM:
				feeder.parser.set_channel_info(channel, dvbt_chan_to_freq(channel),
							       ((channel <= 12) ?
								"INVERSION_AUTO:BANDWIDTH_7_MHZ:FEC_AUTO:FEC_AUTO:QAM_AUTO:TRANSMISSION_MODE_AUTO:GUARD_INTERVAL_AUTO:HIERARCHY_AUTO" :
								"INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_AUTO:FEC_AUTO:QAM_AUTO:TRANSMISSION_MODE_AUTO:GUARD_INTERVAL_AUTO:HIERARCHY_AUTO"));
				break;
			}
			if (0 == start_feed()) {
				int timeout = (scan_epg) ? 16 : (fe_type == DVBTEE_FE_ATSC) ? 4 : 12;
				while ((!f_kill_thread) && (timeout)) {
					if (scan_epg)
						feeder.wait_for_epg(1000);
					else
						feeder.wait_for_psip(1000);
					timeout--;
				}
				stop_feed();
				channels[channel] = feeder.parser.get_ts_id();
			} // else what if we cant start the feed???
		}
	}
	close_fe();
	scan_complete = true;
	state &= ~TUNE_STATE_SCAN;
	}
	pthread_exit(NULL);
}

#define CHAR_CMD_COMMA ","

int tune::start_scan(unsigned int mode, char *channel_list, bool epg, scan_progress_callback progress_cb, void *progress_context)
{
	char *save;
	char *item = strtok_r(channel_list, CHAR_CMD_COMMA, &save);

	scan_channel_list.clear();

	if (item) while (item) {
#if 0
		if (!item)
			item = channel_list;
#endif
		scan_channel_list[atoi(item)] = false;

		item = strtok_r(NULL, CHAR_CMD_COMMA, &save);
	} else
		scan_channel_list[atoi(channel_list)] = false;

	return start_scan(mode, epg, progress_cb, progress_context);
}

int tune::start_scan(unsigned int mode, unsigned int min, unsigned int max, bool epg, scan_progress_callback progress_cb, void *progress_context)
{
	//channels.clear();
	scan_channel_list.clear();

	unsigned int scan_min = min;
	unsigned int scan_max = max;

	if (mode != SCAN_QAM)
		mode = SCAN_VSB;

	scan_mode = mode;

	switch (scan_mode) {
	default:
	case SCAN_VSB:
		scan_min = (min) ? min : 2;
		scan_max = (max) ? max : 69;
		break;
	case SCAN_QAM:
		scan_min = (min) ? min : 2;
		scan_max = (max) ? max : 133;
		break;
	}

	for (unsigned int channel = scan_min; channel <= scan_max; channel++)
		scan_channel_list[channel] = false; // TODO: set true if channel found

	return start_scan(mode, epg, progress_cb, progress_context);
}

int tune::start_scan(unsigned int mode, bool epg, scan_progress_callback progress_cb, void *progress_context)
{
	scan_progress_cb = progress_cb;
	scan_progress_context = progress_context;

	if (mode != SCAN_QAM)
		mode = SCAN_VSB;

	scan_mode = mode;

	scan_epg = epg;

	int fd = open_fe();
	if (fd < 0)
		return fd;

	scan_complete = false;
	f_kill_thread = false;

	int ret = pthread_create(&h_thread, NULL, scan_thread, this);
	if (0 != ret) {
		perror("pthread_create() failed");
		close_fe();
	}
	return ret;
}

unsigned int tune::get_scan_results(bool wait, chandump_callback chandump_cb, void* chandump_context)
{
	if (wait) wait_for_scan_complete();

	unsigned int ret = feeder.parser.xine_dump(chandump_cb, chandump_context);

	if (scan_epg) feeder.parser.epg_dump();

	return ret;
}

int tune::scan_for_services(unsigned int mode, char *channel_list, bool epg, scan_progress_callback progress_cb, void* progress_context, chandump_callback chandump_cb, void* chandump_context, bool wait_for_results)
{
	unsigned int count = 0;

	if (!mode)
		mode = SCAN_VSB;

	if (0 != start_scan(scan_mode, channel_list, epg, progress_cb, progress_context))
		return -1;

	if (wait_for_results) {
		count += get_scan_results(true, chandump_cb, chandump_context);
		fprintf(stderr, "found %d services\n", count);
	}
	return 0;
}

int tune::scan_for_services(unsigned int mode, unsigned int min, unsigned int max, bool epg, scan_progress_callback progress_cb, void* progress_context, chandump_callback chandump_cb, void* chandump_context, bool wait_for_results)
{
	unsigned int count = 0;
	unsigned int total_count = 0;

	if (!mode)
		mode = SCAN_VSB;

	for (scan_mode = SCAN_VSB; scan_mode <= SCAN_QAM; scan_mode++) if (mode & scan_mode) {

		count = 0;

		if (0 != start_scan(scan_mode, min, max, epg, progress_cb, progress_context))
			return -1;

		if (wait_for_results) {

			count += get_scan_results(true, chandump_cb, chandump_context);
			total_count += count;
#if 0
			for (map_chan_to_ts_id::const_iterator iter = channels.begin(); iter != channels.end(); ++iter)
				fprintf(stderr, "found ts_id %05d on channel %d\n", iter->second, iter->first);
			channels.clear(); //
#endif
			fprintf(stderr, "found %d services\n", count);
		}
	}
	if (count != total_count)
		fprintf(stderr, "found %d services in total\n", total_count);
	return 0;
}
<commit_msg>tune: reset the parser after __tune_channel()<commit_after>/*****************************************************************************
 * Copyright (C) 2011-2013 Michael Krufky
 *
 * Author: Michael Krufky <mkrufky@linuxtv.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <map>

#include "tune.h"
#include "log.h"
#define CLASS_MODULE "tune"

#define dprintf(fmt, arg...) __dprintf(DBG_TUNE, fmt, ##arg)

typedef std::map<unsigned int, uint16_t> map_chan_to_ts_id;

static map_chan_to_ts_id channels;

tune::tune()
  : h_thread((pthread_t)NULL)
  , f_kill_thread(false)
  , state(TUNE_STATE_IDLE)
  , cur_chan(0)
  , time_touched((time_t)0)
  , scan_mode(0)
  , scan_epg(false)
  , scan_complete(false)
  , fe_type(DVBTEE_FE_OFDM)
  , last_query((time_t)0)
  , scan_progress_cb(NULL)
  , scan_progress_context(NULL)
{
	dprintf("()");
//	channels.clear();
}

tune::~tune()
{
	dprintf("()");
	stop_feed();
	close_fe();
//	channels.clear();
}

tune::tune(const tune&)
{
	dprintf("(copy)");

//	channels.clear();
	feeder.parser.cleanup();
	h_thread = (pthread_t)NULL;
	f_kill_thread = false;
	cur_chan = 0;
	state = TUNE_STATE_IDLE;
	time_touched = (time_t)0;
	scan_mode = 0;
	scan_epg = false;
	scan_complete = false;
	fe_type = DVBTEE_FE_OFDM;
	last_query = (time_t)0;
	scan_progress_cb = NULL;
	scan_progress_context = NULL;
}

tune& tune::operator= (const tune& cSource)
{
	dprintf("(operator=)");

	if (this == &cSource)
		return *this;

//	channels.clear();
	feeder.parser.cleanup();
	h_thread = (pthread_t)NULL;
	f_kill_thread = false;
	cur_chan = 0;
	state = TUNE_STATE_IDLE;
	time_touched = (time_t)0;
	scan_mode = 0;
	scan_epg = false;
	scan_complete = false;
	fe_type = DVBTEE_FE_OFDM;
	last_query = (time_t)0;
	scan_progress_cb = NULL;
	scan_progress_context = NULL;

	return *this;
}

int tune::close_fe() {
	cur_chan = 0;
	state &= ~TUNE_STATE_OPEN;
	state &= ~TUNE_STATE_LOCK;
	return 0;
}

bool tune::wait_for_lock_or_timeout(unsigned int time_ms)
{
	unsigned int status = (dvbtee_fe_status_t)0;
	time_t start_time = time(NULL);
	while ((0 == ((status |= fe_status()) & DVBTEE_FE_HAS_LOCK)) && ( (time(NULL) - start_time) < ((int)time_ms / 1000) ))
		usleep(200*1000);
	if ((status & (DVBTEE_FE_HAS_LOCK | DVBTEE_FE_HAS_SYNC)) == DVBTEE_FE_HAS_SYNC) {
		start_time = time(NULL);
		while ((0 == ((status |= fe_status()) & DVBTEE_FE_HAS_LOCK)) && ( (time(NULL) - start_time) < (2 * (int)time_ms / 1000) ))
			usleep(200*1000);
	}
	return ((status & DVBTEE_FE_HAS_LOCK) == DVBTEE_FE_HAS_LOCK);
}

bool tune::tune_channel(dvbtee_fe_modulation_t modulation, unsigned int channel)
{
	bool ret = __tune_channel(modulation, channel);

	feeder.parser.reset();

	return ret;
}

void tune::stop_feed()
{
	feeder.stop();
	state &= ~TUNE_STATE_FEED;
	feeder.close_file();
}

time_t tune::last_touched() // sec_ago
{
	time_t timenow;
	time(&timenow);
	time_t ret = timenow - time_touched;
	if (timenow - last_query)
		dprintf("last touched %ld seconds ago", ret);
	time(&last_query);
	return ret;
}

//static
void* tune::scan_thread(void *p_this)
{
	return static_cast<tune*>(p_this)->scan_thread();
}

void* tune::scan_thread()
{
	if (!is_scan()) {

	scan_progress_t progress;

	progress.total = (unsigned int)scan_channel_list.size(),
	progress.current = 0,
	progress.physical_channel = 0,

	state |= TUNE_STATE_SCAN;

	feeder.parser.set_scan_mode(true);
	feeder.parser.set_epg_mode(scan_epg);

	for (channel_map::const_iterator iter = scan_channel_list.begin(); iter != scan_channel_list.end(); ++iter) {
		unsigned int channel = iter->first;
		progress.current++;
		progress.physical_channel = channel;

		if (f_kill_thread)
			break;
#if 0
		map_chan_to_ts_id::const_iterator iter = channels.find(channel);
		if (iter != channels.end()) {
#else
		if (channels.count(channel)) {
#endif
			fprintf(stderr, "ALREADY SCANNED CHANNEL %d\n", channel);
			continue;
		}

		fprintf(stderr, "scan channel %d...\n", channel);

		if (scan_progress_cb)
			scan_progress_cb(scan_progress_context, &progress);

		if ((!f_kill_thread) && ((tune_channel((scan_mode == SCAN_VSB) ? DVBTEE_VSB_8 : DVBTEE_QAM_256, channel)) && (wait_for_lock_or_timeout(2000)))) {

			if (f_kill_thread)
				break;

			switch (fe_type) {
			default:
			case DVBTEE_FE_ATSC:
				feeder.parser.set_channel_info(channel,
							       (scan_mode == SCAN_VSB) ? atsc_vsb_chan_to_freq(channel) : atsc_qam_chan_to_freq(channel),
							       (scan_mode == SCAN_VSB) ? "8VSB" : "QAM_256");
				break;
			case DVBTEE_FE_OFDM:
				feeder.parser.set_channel_info(channel, dvbt_chan_to_freq(channel),
							       ((channel <= 12) ?
								"INVERSION_AUTO:BANDWIDTH_7_MHZ:FEC_AUTO:FEC_AUTO:QAM_AUTO:TRANSMISSION_MODE_AUTO:GUARD_INTERVAL_AUTO:HIERARCHY_AUTO" :
								"INVERSION_AUTO:BANDWIDTH_8_MHZ:FEC_AUTO:FEC_AUTO:QAM_AUTO:TRANSMISSION_MODE_AUTO:GUARD_INTERVAL_AUTO:HIERARCHY_AUTO"));
				break;
			}
			if (0 == start_feed()) {
				int timeout = (scan_epg) ? 16 : (fe_type == DVBTEE_FE_ATSC) ? 4 : 12;
				while ((!f_kill_thread) && (timeout)) {
					if (scan_epg)
						feeder.wait_for_epg(1000);
					else
						feeder.wait_for_psip(1000);
					timeout--;
				}
				stop_feed();
				channels[channel] = feeder.parser.get_ts_id();
			} // else what if we cant start the feed???
		}
	}
	close_fe();
	scan_complete = true;
	state &= ~TUNE_STATE_SCAN;
	}
	pthread_exit(NULL);
}

#define CHAR_CMD_COMMA ","

int tune::start_scan(unsigned int mode, char *channel_list, bool epg, scan_progress_callback progress_cb, void *progress_context)
{
	char *save;
	char *item = strtok_r(channel_list, CHAR_CMD_COMMA, &save);

	scan_channel_list.clear();

	if (item) while (item) {
#if 0
		if (!item)
			item = channel_list;
#endif
		scan_channel_list[atoi(item)] = false;

		item = strtok_r(NULL, CHAR_CMD_COMMA, &save);
	} else
		scan_channel_list[atoi(channel_list)] = false;

	return start_scan(mode, epg, progress_cb, progress_context);
}

int tune::start_scan(unsigned int mode, unsigned int min, unsigned int max, bool epg, scan_progress_callback progress_cb, void *progress_context)
{
	//channels.clear();
	scan_channel_list.clear();

	unsigned int scan_min = min;
	unsigned int scan_max = max;

	if (mode != SCAN_QAM)
		mode = SCAN_VSB;

	scan_mode = mode;

	switch (scan_mode) {
	default:
	case SCAN_VSB:
		scan_min = (min) ? min : 2;
		scan_max = (max) ? max : 69;
		break;
	case SCAN_QAM:
		scan_min = (min) ? min : 2;
		scan_max = (max) ? max : 133;
		break;
	}

	for (unsigned int channel = scan_min; channel <= scan_max; channel++)
		scan_channel_list[channel] = false; // TODO: set true if channel found

	return start_scan(mode, epg, progress_cb, progress_context);
}

int tune::start_scan(unsigned int mode, bool epg, scan_progress_callback progress_cb, void *progress_context)
{
	scan_progress_cb = progress_cb;
	scan_progress_context = progress_context;

	if (mode != SCAN_QAM)
		mode = SCAN_VSB;

	scan_mode = mode;

	scan_epg = epg;

	int fd = open_fe();
	if (fd < 0)
		return fd;

	scan_complete = false;
	f_kill_thread = false;

	int ret = pthread_create(&h_thread, NULL, scan_thread, this);
	if (0 != ret) {
		perror("pthread_create() failed");
		close_fe();
	}
	return ret;
}

unsigned int tune::get_scan_results(bool wait, chandump_callback chandump_cb, void* chandump_context)
{
	if (wait) wait_for_scan_complete();

	unsigned int ret = feeder.parser.xine_dump(chandump_cb, chandump_context);

	if (scan_epg) feeder.parser.epg_dump();

	return ret;
}

int tune::scan_for_services(unsigned int mode, char *channel_list, bool epg, scan_progress_callback progress_cb, void* progress_context, chandump_callback chandump_cb, void* chandump_context, bool wait_for_results)
{
	unsigned int count = 0;

	if (!mode)
		mode = SCAN_VSB;

	if (0 != start_scan(scan_mode, channel_list, epg, progress_cb, progress_context))
		return -1;

	if (wait_for_results) {
		count += get_scan_results(true, chandump_cb, chandump_context);
		fprintf(stderr, "found %d services\n", count);
	}
	return 0;
}

int tune::scan_for_services(unsigned int mode, unsigned int min, unsigned int max, bool epg, scan_progress_callback progress_cb, void* progress_context, chandump_callback chandump_cb, void* chandump_context, bool wait_for_results)
{
	unsigned int count = 0;
	unsigned int total_count = 0;

	if (!mode)
		mode = SCAN_VSB;

	for (scan_mode = SCAN_VSB; scan_mode <= SCAN_QAM; scan_mode++) if (mode & scan_mode) {

		count = 0;

		if (0 != start_scan(scan_mode, min, max, epg, progress_cb, progress_context))
			return -1;

		if (wait_for_results) {

			count += get_scan_results(true, chandump_cb, chandump_context);
			total_count += count;
#if 0
			for (map_chan_to_ts_id::const_iterator iter = channels.begin(); iter != channels.end(); ++iter)
				fprintf(stderr, "found ts_id %05d on channel %d\n", iter->second, iter->first);
			channels.clear(); //
#endif
			fprintf(stderr, "found %d services\n", count);
		}
	}
	if (count != total_count)
		fprintf(stderr, "found %d services in total\n", total_count);
	return 0;
}
<|endoftext|>


<commit_before>#include "Test.h"
#include "SkPoint.h"
#include "SkRandom.h"

#if defined(SkLONGLONG)
static int symmetric_fixmul(int a, int b) {
    int sa = SkExtractSign(a);
    int sb = SkExtractSign(b);

    a = SkApplySign(a, sa);
    b = SkApplySign(b, sb);

#if 1
    int c = (int)(((SkLONGLONG)a * b) >> 16);

    return SkApplySign(c, sa ^ sb);
#else
    SkLONGLONG ab = (SkLONGLONG)a * b;
    if (sa ^ sb) {
        ab = -ab;
    }
    return ab >> 16;
#endif
}
#endif

static void check_length(skiatest::Reporter* reporter,
                         const SkPoint& p, SkScalar targetLen) {
#ifdef SK_CAN_USE_FLOAT
    float x = SkScalarToFloat(p.fX);
    float y = SkScalarToFloat(p.fY);
    float len = sk_float_sqrt(x*x + y*y);

    len /= SkScalarToFloat(targetLen);

    REPORTER_ASSERT(reporter, len > 0.999f && len < 1.001f);
#endif
}

#if defined(SK_CAN_USE_FLOAT)

static float nextFloat(SkRandom& rand) {
    SkFloatIntUnion data;
    data.fSignBitInt = rand.nextU();
    return data.fFloat;
}

/*  returns true if a == b as resulting from (int)x. Since it is undefined
 what to do if the float exceeds 2^32-1, we check for that explicitly.
 */
static bool equal_float_native_skia(float x, uint32_t ni, uint32_t si) {
    if (!(x == x)) {    // NAN
        return si == SK_MaxS32 || si == SK_MinS32;
    }
    // for out of range, C is undefined, but skia always should return NaN32
    if (x > SK_MaxS32) {
        return si == SK_MaxS32;
    }
    if (x < -SK_MaxS32) {
        return si == SK_MinS32;
    }
    return si == ni;
}

static void assert_float_equal(skiatest::Reporter* reporter, const char op[],
                               float x, uint32_t ni, uint32_t si) {
    if (!equal_float_native_skia(x, ni, si)) {
        SkString desc;
        desc.printf("%s float %g bits %x native %x skia %x\n", op, x, ni, si);
        reporter->reportFailed(desc);
    }
}

static void test_float_cast(skiatest::Reporter* reporter, float x) {
    int ix = (int)x;
    int iix = SkFloatToIntCast(x);
    assert_float_equal(reporter, "cast", x, ix, iix);
}

static void test_float_floor(skiatest::Reporter* reporter, float x) {
    int ix = (int)floor(x);
    int iix = SkFloatToIntFloor(x);
    assert_float_equal(reporter, "floor", x, ix, iix);
}

static void test_float_round(skiatest::Reporter* reporter, float x) {
    double xx = x + 0.5;    // need intermediate double to avoid temp loss
    int ix = (int)floor(xx);
    int iix = SkFloatToIntRound(x);
    assert_float_equal(reporter, "round", x, ix, iix);
}

static void test_float_ceil(skiatest::Reporter* reporter, float x) {
    int ix = (int)ceil(x);
    int iix = SkFloatToIntCeil(x);
    assert_float_equal(reporter, "ceil", x, ix, iix);
}

static void test_float_conversions(skiatest::Reporter* reporter, float x) {
    test_float_cast(reporter, x);
    test_float_floor(reporter, x);
    test_float_round(reporter, x);
    test_float_ceil(reporter, x);
}

static void test_int2float(skiatest::Reporter* reporter, int ival) {
    float x0 = (float)ival;
    float x1 = SkIntToFloatCast(ival);
    float x2 = SkIntToFloatCast_NoOverflowCheck(ival);
    REPORTER_ASSERT(reporter, x0 == x1);
    REPORTER_ASSERT(reporter, x0 == x2);
}

static void unittest_fastfloat(skiatest::Reporter* reporter) {
    SkRandom rand;
    size_t i;

    static const float gFloats[] = {
        0.f, 1.f, 0.5f, 0.499999f, 0.5000001f, 1.f/3,
        0.000000001f, 1000000000.f,     // doesn't overflow
        0.0000000001f, 10000000000.f    // does overflow
    };
    for (i = 0; i < SK_ARRAY_COUNT(gFloats); i++) {
        test_float_conversions(reporter, gFloats[i]);
        test_float_conversions(reporter, -gFloats[i]);
    }

    for (int outer = 0; outer < 100; outer++) {
        rand.setSeed(outer);
        for (i = 0; i < 100000; i++) {
            float x = nextFloat(rand);
            test_float_conversions(reporter, x);
        }

        test_int2float(reporter, 0);
        test_int2float(reporter, 1);
        test_int2float(reporter, -1);
        for (i = 0; i < 100000; i++) {
            // for now only test ints that are 24bits or less, since we don't
            // round (down) large ints the same as IEEE...
            int ival = rand.nextU() & 0xFFFFFF;
            test_int2float(reporter, ival);
            test_int2float(reporter, -ival);
        }
    }
}

#endif

static void test_muldiv255(skiatest::Reporter* reporter) {
#ifdef SK_CAN_USE_FLOAT
    for (int a = 0; a <= 255; a++) {
        for (int b = 0; b <= 255; b++) {
            int ab = a * b;
            float s = ab / 255.0f;
            int round = (int)floorf(s + 0.5f);
            int trunc = (int)floorf(s);

            int iround = SkMulDiv255Round(a, b);
            int itrunc = SkMulDiv255Trunc(a, b);

            REPORTER_ASSERT(reporter, iround == round);
            REPORTER_ASSERT(reporter, itrunc == trunc);

            REPORTER_ASSERT(reporter, itrunc <= iround);
            REPORTER_ASSERT(reporter, iround <= a);
            REPORTER_ASSERT(reporter, iround <= b);
        }
    }
#endif
}

static void TestMath(skiatest::Reporter* reporter) {
    int         i;
    int32_t     x;
    SkRandom    rand;

    // these should assert
#if 0
    SkToS8(128);
    SkToS8(-129);
    SkToU8(256);
    SkToU8(-5);

    SkToS16(32768);
    SkToS16(-32769);
    SkToU16(65536);
    SkToU16(-5);

    if (sizeof(size_t) > 4) {
        SkToS32(4*1024*1024);
        SkToS32(-4*1024*1024);
        SkToU32(5*1024*1024);
        SkToU32(-5);
    }
#endif

    test_muldiv255(reporter);

    {
        SkScalar x = SK_ScalarNaN;
        REPORTER_ASSERT(reporter, SkScalarIsNaN(x));
    }

    for (i = 1; i <= 10; i++) {
        x = SkCubeRootBits(i*i*i, 11);
        REPORTER_ASSERT(reporter, x == i);
    }

    x = SkFixedSqrt(SK_Fixed1);
    REPORTER_ASSERT(reporter, x == SK_Fixed1);
    x = SkFixedSqrt(SK_Fixed1/4);
    REPORTER_ASSERT(reporter, x == SK_Fixed1/2);
    x = SkFixedSqrt(SK_Fixed1*4);
    REPORTER_ASSERT(reporter, x == SK_Fixed1*2);

    x = SkFractSqrt(SK_Fract1);
    REPORTER_ASSERT(reporter, x == SK_Fract1);
    x = SkFractSqrt(SK_Fract1/4);
    REPORTER_ASSERT(reporter, x == SK_Fract1/2);
    x = SkFractSqrt(SK_Fract1/16);
    REPORTER_ASSERT(reporter, x == SK_Fract1/4);

    for (i = 1; i < 100; i++) {
        x = SkFixedSqrt(SK_Fixed1 * i * i);
        REPORTER_ASSERT(reporter, x == SK_Fixed1 * i);
    }

    for (i = 0; i < 1000; i++) {
        int value = rand.nextS16();
        int max = rand.nextU16();

        int clamp = SkClampMax(value, max);
        int clamp2 = value < 0 ? 0 : (value > max ? max : value);
        REPORTER_ASSERT(reporter, clamp == clamp2);
    }

    for (i = 0; i < 10000; i++) {
        SkPoint p;

        p.setLength(rand.nextS(), rand.nextS(), SK_Scalar1);
        check_length(reporter, p, SK_Scalar1);
        p.setLength(rand.nextS() >> 13, rand.nextS() >> 13, SK_Scalar1);
        check_length(reporter, p, SK_Scalar1);
    }

    {
        SkFixed result = SkFixedDiv(100, 100);
        REPORTER_ASSERT(reporter, result == SK_Fixed1);
        result = SkFixedDiv(1, SK_Fixed1);
        REPORTER_ASSERT(reporter, result == 1);
    }

#ifdef SK_CAN_USE_FLOAT
    unittest_fastfloat(reporter);
#endif

#ifdef SkLONGLONG
    for (i = 0; i < 10000; i++) {
        SkFixed numer = rand.nextS();
        SkFixed denom = rand.nextS();
        SkFixed result = SkFixedDiv(numer, denom);
        SkLONGLONG check = ((SkLONGLONG)numer << 16) / denom;

        (void)SkCLZ(numer);
        (void)SkCLZ(denom);

        REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
        if (check > SK_MaxS32) {
            check = SK_MaxS32;
        } else if (check < -SK_MaxS32) {
            check = SK_MinS32;
        }
        REPORTER_ASSERT(reporter, result == (int32_t)check);

        result = SkFractDiv(numer, denom);
        check = ((SkLONGLONG)numer << 30) / denom;

        REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
        if (check > SK_MaxS32) {
            check = SK_MaxS32;
        } else if (check < -SK_MaxS32) {
            check = SK_MinS32;
        }
        REPORTER_ASSERT(reporter, result == (int32_t)check);

        // make them <= 2^24, so we don't overflow in fixmul
        numer = numer << 8 >> 8;
        denom = denom << 8 >> 8;

        result = SkFixedMul(numer, denom);
        SkFixed r2 = symmetric_fixmul(numer, denom);
        //        SkASSERT(result == r2);

        result = SkFixedMul(numer, numer);
        r2 = SkFixedSquare(numer);
        REPORTER_ASSERT(reporter, result == r2);

#ifdef SK_CAN_USE_FLOAT
        if (numer >= 0 && denom >= 0) {
            SkFixed mean = SkFixedMean(numer, denom);
            float prod = SkFixedToFloat(numer) * SkFixedToFloat(denom);
            float fm = sk_float_sqrt(sk_float_abs(prod));
            SkFixed mean2 = SkFloatToFixed(fm);
            int diff = SkAbs32(mean - mean2);
            REPORTER_ASSERT(reporter, diff <= 1);
        }

        {
            SkFixed mod = SkFixedMod(numer, denom);
            float n = SkFixedToFloat(numer);
            float d = SkFixedToFloat(denom);
            float m = sk_float_mod(n, d);
            // ensure the same sign
            REPORTER_ASSERT(reporter, mod == 0 || (mod < 0) == (m < 0));
            int diff = SkAbs32(mod - SkFloatToFixed(m));
            REPORTER_ASSERT(reporter, (diff >> 7) == 0);
        }
#endif
    }
#endif

#ifdef SK_CAN_USE_FLOAT
    for (i = 0; i < 10000; i++) {
        SkFract x = rand.nextU() >> 1;
        double xx = (double)x / SK_Fract1;
        SkFract xr = SkFractSqrt(x);
        SkFract check = SkFloatToFract(sqrt(xx));
        REPORTER_ASSERT(reporter, xr == check ||
                                  xr == check-1 ||
                                  xr == check+1);

        xr = SkFixedSqrt(x);
        xx = (double)x / SK_Fixed1;
        check = SkFloatToFixed(sqrt(xx));
        REPORTER_ASSERT(reporter, xr == check || xr == check-1);

        xr = SkSqrt32(x);
        xx = (double)x;
        check = (int32_t)sqrt(xx);
        REPORTER_ASSERT(reporter, xr == check || xr == check-1);
    }
#endif

#if !defined(SK_SCALAR_IS_FLOAT) && defined(SK_CAN_USE_FLOAT)
    {
        SkFixed s, c;
        s = SkFixedSinCos(0, &c);
        REPORTER_ASSERT(reporter, s == 0);
        REPORTER_ASSERT(reporter, c == SK_Fixed1);
    }

    int maxDiff = 0;
    for (i = 0; i < 1000; i++) {
        SkFixed rads = rand.nextS() >> 10;
        double frads = SkFixedToFloat(rads);

        SkFixed s, c;
        s = SkScalarSinCos(rads, &c);

        double fs = sin(frads);
        double fc = cos(frads);

        SkFixed is = SkFloatToFixed(fs);
        SkFixed ic = SkFloatToFixed(fc);

        maxDiff = SkMax32(maxDiff, SkAbs32(is - s));
        maxDiff = SkMax32(maxDiff, SkAbs32(ic - c));
    }
    SkDebugf("SinCos: maximum error = %d\n", maxDiff);
#endif
}

#include "TestClassDef.h"
DEFINE_TESTCLASS("Math", MathTestClass, TestMath)
<commit_msg>add unittest for copysign<commit_after>#include "Test.h"
#include "SkPoint.h"
#include "SkRandom.h"

#if defined(SkLONGLONG)
static int symmetric_fixmul(int a, int b) {
    int sa = SkExtractSign(a);
    int sb = SkExtractSign(b);

    a = SkApplySign(a, sa);
    b = SkApplySign(b, sb);

#if 1
    int c = (int)(((SkLONGLONG)a * b) >> 16);

    return SkApplySign(c, sa ^ sb);
#else
    SkLONGLONG ab = (SkLONGLONG)a * b;
    if (sa ^ sb) {
        ab = -ab;
    }
    return ab >> 16;
#endif
}
#endif

static void check_length(skiatest::Reporter* reporter,
                         const SkPoint& p, SkScalar targetLen) {
#ifdef SK_CAN_USE_FLOAT
    float x = SkScalarToFloat(p.fX);
    float y = SkScalarToFloat(p.fY);
    float len = sk_float_sqrt(x*x + y*y);

    len /= SkScalarToFloat(targetLen);

    REPORTER_ASSERT(reporter, len > 0.999f && len < 1.001f);
#endif
}

#if defined(SK_CAN_USE_FLOAT)

static float nextFloat(SkRandom& rand) {
    SkFloatIntUnion data;
    data.fSignBitInt = rand.nextU();
    return data.fFloat;
}

/*  returns true if a == b as resulting from (int)x. Since it is undefined
 what to do if the float exceeds 2^32-1, we check for that explicitly.
 */
static bool equal_float_native_skia(float x, uint32_t ni, uint32_t si) {
    if (!(x == x)) {    // NAN
        return si == SK_MaxS32 || si == SK_MinS32;
    }
    // for out of range, C is undefined, but skia always should return NaN32
    if (x > SK_MaxS32) {
        return si == SK_MaxS32;
    }
    if (x < -SK_MaxS32) {
        return si == SK_MinS32;
    }
    return si == ni;
}

static void assert_float_equal(skiatest::Reporter* reporter, const char op[],
                               float x, uint32_t ni, uint32_t si) {
    if (!equal_float_native_skia(x, ni, si)) {
        SkString desc;
        desc.printf("%s float %g bits %x native %x skia %x\n", op, x, ni, si);
        reporter->reportFailed(desc);
    }
}

static void test_float_cast(skiatest::Reporter* reporter, float x) {
    int ix = (int)x;
    int iix = SkFloatToIntCast(x);
    assert_float_equal(reporter, "cast", x, ix, iix);
}

static void test_float_floor(skiatest::Reporter* reporter, float x) {
    int ix = (int)floor(x);
    int iix = SkFloatToIntFloor(x);
    assert_float_equal(reporter, "floor", x, ix, iix);
}

static void test_float_round(skiatest::Reporter* reporter, float x) {
    double xx = x + 0.5;    // need intermediate double to avoid temp loss
    int ix = (int)floor(xx);
    int iix = SkFloatToIntRound(x);
    assert_float_equal(reporter, "round", x, ix, iix);
}

static void test_float_ceil(skiatest::Reporter* reporter, float x) {
    int ix = (int)ceil(x);
    int iix = SkFloatToIntCeil(x);
    assert_float_equal(reporter, "ceil", x, ix, iix);
}

static void test_float_conversions(skiatest::Reporter* reporter, float x) {
    test_float_cast(reporter, x);
    test_float_floor(reporter, x);
    test_float_round(reporter, x);
    test_float_ceil(reporter, x);
}

static void test_int2float(skiatest::Reporter* reporter, int ival) {
    float x0 = (float)ival;
    float x1 = SkIntToFloatCast(ival);
    float x2 = SkIntToFloatCast_NoOverflowCheck(ival);
    REPORTER_ASSERT(reporter, x0 == x1);
    REPORTER_ASSERT(reporter, x0 == x2);
}

static void unittest_fastfloat(skiatest::Reporter* reporter) {
    SkRandom rand;
    size_t i;

    static const float gFloats[] = {
        0.f, 1.f, 0.5f, 0.499999f, 0.5000001f, 1.f/3,
        0.000000001f, 1000000000.f,     // doesn't overflow
        0.0000000001f, 10000000000.f    // does overflow
    };
    for (i = 0; i < SK_ARRAY_COUNT(gFloats); i++) {
        test_float_conversions(reporter, gFloats[i]);
        test_float_conversions(reporter, -gFloats[i]);
    }

    for (int outer = 0; outer < 100; outer++) {
        rand.setSeed(outer);
        for (i = 0; i < 100000; i++) {
            float x = nextFloat(rand);
            test_float_conversions(reporter, x);
        }

        test_int2float(reporter, 0);
        test_int2float(reporter, 1);
        test_int2float(reporter, -1);
        for (i = 0; i < 100000; i++) {
            // for now only test ints that are 24bits or less, since we don't
            // round (down) large ints the same as IEEE...
            int ival = rand.nextU() & 0xFFFFFF;
            test_int2float(reporter, ival);
            test_int2float(reporter, -ival);
        }
    }
}

#endif

static void test_muldiv255(skiatest::Reporter* reporter) {
#ifdef SK_CAN_USE_FLOAT
    for (int a = 0; a <= 255; a++) {
        for (int b = 0; b <= 255; b++) {
            int ab = a * b;
            float s = ab / 255.0f;
            int round = (int)floorf(s + 0.5f);
            int trunc = (int)floorf(s);

            int iround = SkMulDiv255Round(a, b);
            int itrunc = SkMulDiv255Trunc(a, b);

            REPORTER_ASSERT(reporter, iround == round);
            REPORTER_ASSERT(reporter, itrunc == trunc);

            REPORTER_ASSERT(reporter, itrunc <= iround);
            REPORTER_ASSERT(reporter, iround <= a);
            REPORTER_ASSERT(reporter, iround <= b);
        }
    }
#endif
}

static void test_copysign(skiatest::Reporter* reporter) {
    static const int32_t gTriples[] = {
        // x, y, expected result
        0, 0, 0,
        0, 1, 0,
        0, -1, 0,
        1, 0, 1,
        1, 1, 1,
        1, -1, -1,
        -1, 0, 1,
        -1, 1, 1,
        -1, -1, -1,
    };
    for (size_t i = 0; i < SK_ARRAY_COUNT(gTriples); i += 3) {
        REPORTER_ASSERT(reporter,
                        SkCopySign32(gTriples[i], gTriples[i+1]) == gTriples[i+2]);
#ifdef SK_CAN_USE_FLOAT
        float x = (float)gTriples[i];
        float y = (float)gTriples[i+1];
        float expected = (float)gTriples[i+2];
        REPORTER_ASSERT(reporter, sk_float_copysign(x, y) == expected);
#endif
    }

    SkRandom rand;
    for (int j = 0; j < 1000; j++) {
        int ix = rand.nextS();
        REPORTER_ASSERT(reporter, SkCopySign32(ix, ix) == ix);
        REPORTER_ASSERT(reporter, SkCopySign32(ix, -ix) == -ix);
        REPORTER_ASSERT(reporter, SkCopySign32(-ix, ix) == ix);
        REPORTER_ASSERT(reporter, SkCopySign32(-ix, -ix) == -ix);

        SkScalar sx = rand.nextSScalar1();
        REPORTER_ASSERT(reporter, SkScalarCopySign(sx, sx) == sx);
        REPORTER_ASSERT(reporter, SkScalarCopySign(sx, -sx) == -sx);
        REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, sx) == sx);
        REPORTER_ASSERT(reporter, SkScalarCopySign(-sx, -sx) == -sx);
    }
}

static void TestMath(skiatest::Reporter* reporter) {
    int         i;
    int32_t     x;
    SkRandom    rand;

    // these should assert
#if 0
    SkToS8(128);
    SkToS8(-129);
    SkToU8(256);
    SkToU8(-5);

    SkToS16(32768);
    SkToS16(-32769);
    SkToU16(65536);
    SkToU16(-5);

    if (sizeof(size_t) > 4) {
        SkToS32(4*1024*1024);
        SkToS32(-4*1024*1024);
        SkToU32(5*1024*1024);
        SkToU32(-5);
    }
#endif

    test_muldiv255(reporter);
    test_copysign(reporter);

    {
        SkScalar x = SK_ScalarNaN;
        REPORTER_ASSERT(reporter, SkScalarIsNaN(x));
    }

    for (i = 1; i <= 10; i++) {
        x = SkCubeRootBits(i*i*i, 11);
        REPORTER_ASSERT(reporter, x == i);
    }

    x = SkFixedSqrt(SK_Fixed1);
    REPORTER_ASSERT(reporter, x == SK_Fixed1);
    x = SkFixedSqrt(SK_Fixed1/4);
    REPORTER_ASSERT(reporter, x == SK_Fixed1/2);
    x = SkFixedSqrt(SK_Fixed1*4);
    REPORTER_ASSERT(reporter, x == SK_Fixed1*2);

    x = SkFractSqrt(SK_Fract1);
    REPORTER_ASSERT(reporter, x == SK_Fract1);
    x = SkFractSqrt(SK_Fract1/4);
    REPORTER_ASSERT(reporter, x == SK_Fract1/2);
    x = SkFractSqrt(SK_Fract1/16);
    REPORTER_ASSERT(reporter, x == SK_Fract1/4);

    for (i = 1; i < 100; i++) {
        x = SkFixedSqrt(SK_Fixed1 * i * i);
        REPORTER_ASSERT(reporter, x == SK_Fixed1 * i);
    }

    for (i = 0; i < 1000; i++) {
        int value = rand.nextS16();
        int max = rand.nextU16();

        int clamp = SkClampMax(value, max);
        int clamp2 = value < 0 ? 0 : (value > max ? max : value);
        REPORTER_ASSERT(reporter, clamp == clamp2);
    }

    for (i = 0; i < 10000; i++) {
        SkPoint p;

        p.setLength(rand.nextS(), rand.nextS(), SK_Scalar1);
        check_length(reporter, p, SK_Scalar1);
        p.setLength(rand.nextS() >> 13, rand.nextS() >> 13, SK_Scalar1);
        check_length(reporter, p, SK_Scalar1);
    }

    {
        SkFixed result = SkFixedDiv(100, 100);
        REPORTER_ASSERT(reporter, result == SK_Fixed1);
        result = SkFixedDiv(1, SK_Fixed1);
        REPORTER_ASSERT(reporter, result == 1);
    }

#ifdef SK_CAN_USE_FLOAT
    unittest_fastfloat(reporter);
#endif

#ifdef SkLONGLONG
    for (i = 0; i < 10000; i++) {
        SkFixed numer = rand.nextS();
        SkFixed denom = rand.nextS();
        SkFixed result = SkFixedDiv(numer, denom);
        SkLONGLONG check = ((SkLONGLONG)numer << 16) / denom;

        (void)SkCLZ(numer);
        (void)SkCLZ(denom);

        REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
        if (check > SK_MaxS32) {
            check = SK_MaxS32;
        } else if (check < -SK_MaxS32) {
            check = SK_MinS32;
        }
        REPORTER_ASSERT(reporter, result == (int32_t)check);

        result = SkFractDiv(numer, denom);
        check = ((SkLONGLONG)numer << 30) / denom;

        REPORTER_ASSERT(reporter, result != (SkFixed)SK_NaN32);
        if (check > SK_MaxS32) {
            check = SK_MaxS32;
        } else if (check < -SK_MaxS32) {
            check = SK_MinS32;
        }
        REPORTER_ASSERT(reporter, result == (int32_t)check);

        // make them <= 2^24, so we don't overflow in fixmul
        numer = numer << 8 >> 8;
        denom = denom << 8 >> 8;

        result = SkFixedMul(numer, denom);
        SkFixed r2 = symmetric_fixmul(numer, denom);
        //        SkASSERT(result == r2);

        result = SkFixedMul(numer, numer);
        r2 = SkFixedSquare(numer);
        REPORTER_ASSERT(reporter, result == r2);

#ifdef SK_CAN_USE_FLOAT
        if (numer >= 0 && denom >= 0) {
            SkFixed mean = SkFixedMean(numer, denom);
            float prod = SkFixedToFloat(numer) * SkFixedToFloat(denom);
            float fm = sk_float_sqrt(sk_float_abs(prod));
            SkFixed mean2 = SkFloatToFixed(fm);
            int diff = SkAbs32(mean - mean2);
            REPORTER_ASSERT(reporter, diff <= 1);
        }

        {
            SkFixed mod = SkFixedMod(numer, denom);
            float n = SkFixedToFloat(numer);
            float d = SkFixedToFloat(denom);
            float m = sk_float_mod(n, d);
            // ensure the same sign
            REPORTER_ASSERT(reporter, mod == 0 || (mod < 0) == (m < 0));
            int diff = SkAbs32(mod - SkFloatToFixed(m));
            REPORTER_ASSERT(reporter, (diff >> 7) == 0);
        }
#endif
    }
#endif

#ifdef SK_CAN_USE_FLOAT
    for (i = 0; i < 10000; i++) {
        SkFract x = rand.nextU() >> 1;
        double xx = (double)x / SK_Fract1;
        SkFract xr = SkFractSqrt(x);
        SkFract check = SkFloatToFract(sqrt(xx));
        REPORTER_ASSERT(reporter, xr == check ||
                                  xr == check-1 ||
                                  xr == check+1);

        xr = SkFixedSqrt(x);
        xx = (double)x / SK_Fixed1;
        check = SkFloatToFixed(sqrt(xx));
        REPORTER_ASSERT(reporter, xr == check || xr == check-1);

        xr = SkSqrt32(x);
        xx = (double)x;
        check = (int32_t)sqrt(xx);
        REPORTER_ASSERT(reporter, xr == check || xr == check-1);
    }
#endif

#if !defined(SK_SCALAR_IS_FLOAT) && defined(SK_CAN_USE_FLOAT)
    {
        SkFixed s, c;
        s = SkFixedSinCos(0, &c);
        REPORTER_ASSERT(reporter, s == 0);
        REPORTER_ASSERT(reporter, c == SK_Fixed1);
    }

    int maxDiff = 0;
    for (i = 0; i < 1000; i++) {
        SkFixed rads = rand.nextS() >> 10;
        double frads = SkFixedToFloat(rads);

        SkFixed s, c;
        s = SkScalarSinCos(rads, &c);

        double fs = sin(frads);
        double fc = cos(frads);

        SkFixed is = SkFloatToFixed(fs);
        SkFixed ic = SkFloatToFixed(fc);

        maxDiff = SkMax32(maxDiff, SkAbs32(is - s));
        maxDiff = SkMax32(maxDiff, SkAbs32(ic - c));
    }
    SkDebugf("SinCos: maximum error = %d\n", maxDiff);
#endif
}

#include "TestClassDef.h"
DEFINE_TESTCLASS("Math", MathTestClass, TestMath)
<|endoftext|>


<commit_before>// __BEGIN_LICENSE__
//
// Copyright (C) 2006 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA).  All Rights Reserved.
//
// Copyright 2006 Carnegie Mellon University. All rights reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3.  The NOSA has been approved by the Open Source
// Initiative.  See the file COPYING at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
// __END_LICENSE__

/// \file Core/Cache.cc
///
/// Types and functions to assist cacheing regeneratable data.
///
#include <vw/Core/Cache.h>
#include <vw/Core/Debugging.h>

namespace {
  vw::Cache g_system_cache( 512*1024*1024 );
}

vw::Cache& vw::Cache::system_cache() {
  return g_system_cache;
}

void vw::Cache::allocate( size_t size ) {
  while( m_size+size > m_max_size ) {
    if( ! m_last_valid ) {
      vw_out(WarningMessage) << "Warning: Cached object (" << size << ") larger than requested maximum cache size (" << m_max_size << ")!";
      break;
    }
    m_last_valid->invalidate();
  }
  m_size += size;
  VW_CACHE_DEBUG( vw_out(VerboseDebugMessage) << "Cache allocated " << size << " bytes (" << m_size << " total)" << std::endl; )
}

void vw::Cache::deallocate( size_t size ) {
  m_size -= size;
  VW_CACHE_DEBUG( vw_out(VerboseDebugMessage) << "Cache deallocated " << size << " bytes (" << m_size << " total)" << std::endl; )
}

void vw::Cache::validate( CacheLineBase *line ) {
  if( line == m_first_valid ) return;
  if( line == m_last_valid ) m_last_valid = line->m_prev;
  if( line == m_first_invalid ) m_first_invalid = line->m_next;
  if( line->m_next ) line->m_next->m_prev = line->m_prev;
  if( line->m_prev ) line->m_prev->m_next = line->m_next;
  line->m_next = m_first_valid;
  line->m_prev = 0;
  if( m_first_valid ) m_first_valid->m_prev = line;
  m_first_valid = line;
  if( ! m_last_valid ) m_last_valid = line;
}

void vw::Cache::invalidate( CacheLineBase *line ) {
  if( line == m_first_valid ) m_first_valid = line->m_next;
  if( line == m_last_valid ) m_last_valid = line->m_prev;
  if( line->m_next ) line->m_next->m_prev = line->m_prev;
  if( line->m_prev ) line->m_prev->m_next = line->m_next;
  line->m_next = m_first_invalid;
  line->m_prev = 0;
  if( m_first_invalid ) m_first_invalid->m_prev = line;
  m_first_invalid = line;
}

void vw::Cache::remove( CacheLineBase *line ) {
  if( line == m_first_valid ) m_first_valid = line->m_next;
  if( line == m_last_valid ) m_last_valid = line->m_prev;
  if( line == m_first_invalid ) m_first_invalid = line->m_next;
  if( line->m_next ) line->m_next->m_prev = line->m_prev;
  if( line->m_prev ) line->m_prev->m_next = line->m_next;
  line->m_next = line->m_prev = 0;
}

void vw::Cache::deprioritize( CacheLineBase *line ) {
  if( line == m_last_valid ) return;
  if( line == m_first_valid ) m_first_valid = line->m_next;
  if( line->m_next ) line->m_next->m_prev = line->m_prev;
  if( line->m_prev ) line->m_prev->m_next = line->m_next;
  line->m_prev = m_last_valid;
  line->m_next = 0;
  m_last_valid->m_next = line;
  m_last_valid = line;
}

void vw::Cache::resize( size_t size ) {
  m_max_size = size;
  while( m_size > m_max_size ) {
    VW_ASSERT( m_last_valid, LogicErr() << "Cache is empty but has nonzero size!" );
    m_last_valid->invalidate();
  }
}
<commit_msg>Added a couple of comments.<commit_after>// __BEGIN_LICENSE__
//
// Copyright (C) 2006 United States Government as represented by the
// Administrator of the National Aeronautics and Space Administration
// (NASA).  All Rights Reserved.
//
// Copyright 2006 Carnegie Mellon University. All rights reserved.
//
// This software is distributed under the NASA Open Source Agreement
// (NOSA), version 1.3.  The NOSA has been approved by the Open Source
// Initiative.  See the file COPYING at the top of the distribution
// directory tree for the complete NOSA document.
//
// THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY
// KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT
// LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO
// SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
// A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT
// THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT
// DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE.
//
// __END_LICENSE__

/// \file Core/Cache.cc
///
/// Types and functions to assist cacheing regeneratable data.
///
#include <vw/Core/Cache.h>
#include <vw/Core/Debugging.h>

namespace {
  vw::Cache g_system_cache( 512*1024*1024 );
}

vw::Cache& vw::Cache::system_cache() {
  return g_system_cache;
}

void vw::Cache::allocate( size_t size ) {
  while( m_size+size > m_max_size ) {
    if( ! m_last_valid ) {
      vw_out(WarningMessage) << "Warning: Cached object (" << size << ") larger than requested maximum cache size (" << m_max_size << ")!";
      break;
    }
    m_last_valid->invalidate();
  }
  m_size += size;
  VW_CACHE_DEBUG( vw_out(VerboseDebugMessage) << "Cache allocated " << size << " bytes (" << m_size << " total)" << std::endl; )
}

void vw::Cache::deallocate( size_t size ) {
  m_size -= size;
  VW_CACHE_DEBUG( vw_out(VerboseDebugMessage) << "Cache deallocated " << size << " bytes (" << m_size << " total)" << std::endl; )
}

// Move the cache line to the top of the valid list.
void vw::Cache::validate( CacheLineBase *line ) {
  if( line == m_first_valid ) return;
  if( line == m_last_valid ) m_last_valid = line->m_prev;
  if( line == m_first_invalid ) m_first_invalid = line->m_next;
  if( line->m_next ) line->m_next->m_prev = line->m_prev;
  if( line->m_prev ) line->m_prev->m_next = line->m_next;
  line->m_next = m_first_valid;
  line->m_prev = 0;
  if( m_first_valid ) m_first_valid->m_prev = line;
  m_first_valid = line;
  if( ! m_last_valid ) m_last_valid = line;
}

// Move the cache line to the top of the invalid list.
void vw::Cache::invalidate( CacheLineBase *line ) {
  if( line == m_first_valid ) m_first_valid = line->m_next;
  if( line == m_last_valid ) m_last_valid = line->m_prev;
  if( line->m_next ) line->m_next->m_prev = line->m_prev;
  if( line->m_prev ) line->m_prev->m_next = line->m_next;
  line->m_next = m_first_invalid;
  line->m_prev = 0;
  if( m_first_invalid ) m_first_invalid->m_prev = line;
  m_first_invalid = line;
}

// Remove the cache line from the cache lists.
void vw::Cache::remove( CacheLineBase *line ) {
  if( line == m_first_valid ) m_first_valid = line->m_next;
  if( line == m_last_valid ) m_last_valid = line->m_prev;
  if( line == m_first_invalid ) m_first_invalid = line->m_next;
  if( line->m_next ) line->m_next->m_prev = line->m_prev;
  if( line->m_prev ) line->m_prev->m_next = line->m_next;
  line->m_next = line->m_prev = 0;
}

// Move the cache line to the bottom of the valid list.
void vw::Cache::deprioritize( CacheLineBase *line ) {
  if( line == m_last_valid ) return;
  if( line == m_first_valid ) m_first_valid = line->m_next;
  if( line->m_next ) line->m_next->m_prev = line->m_prev;
  if( line->m_prev ) line->m_prev->m_next = line->m_next;
  line->m_prev = m_last_valid;
  line->m_next = 0;
  m_last_valid->m_next = line;
  m_last_valid = line;
}

void vw::Cache::resize( size_t size ) {
  m_max_size = size;
  while( m_size > m_max_size ) {
    VW_ASSERT( m_last_valid, LogicErr() << "Cache is empty but has nonzero size!" );
    m_last_valid->invalidate();
  }
}
<|endoftext|>


<commit_before>/*
* This file is part of ATLAS. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this distribution.
* (Also avialable at http://www.apache.org/licenses/LICENSE-2.0.txt)
* You may not use this file except in compliance with the License.
*/
#include <iostream>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include "AssimpImporter.hpp"

namespace AssimpWorker {

	AssimpImporter::AssimpImporter() :
		importer()
	{
		return;
	}

	AssimpImporter::~AssimpImporter(){
		return;
	}

	const aiScene* AssimpImporter::importSceneFromFile(std::string fileName, Log& log){
		importer.SetPropertyBool(AI_CONFIG_PP_FD_REMOVE, true); //remove degenerate polys
		importer.SetPropertyBool(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, true); //do not import skeletons
		importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT); //Drop all primitives that aren't triangles
		const aiScene* scene = importer.ReadFile(fileName, aiProcessPreset_TargetRealtime_Quality);
		if (!scene) {
			log.error("Scene not imported: "+fileName);
		}
		log.error(importer.GetErrorString());
		return scene;
	}

}
<commit_msg>AssimpImporter: use SetPropertyInteger for bool flags.<commit_after>/*
* This file is part of ATLAS. It is subject to the license terms in
* the LICENSE file found in the top-level directory of this distribution.
* (Also avialable at http://www.apache.org/licenses/LICENSE-2.0.txt)
* You may not use this file except in compliance with the License.
*/
#include <iostream>
#include <assimp/postprocess.h>
#include <assimp/scene.h>
#include "AssimpImporter.hpp"

namespace AssimpWorker {

	AssimpImporter::AssimpImporter() :
		importer()
	{
		return;
	}

	AssimpImporter::~AssimpImporter(){
		return;
	}

	const aiScene* AssimpImporter::importSceneFromFile(std::string fileName, Log& log){
		importer.SetPropertyInteger(AI_CONFIG_PP_FD_REMOVE, true); //remove degenerate polys
		importer.SetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, true); //do not import skeletons
		importer.SetPropertyInteger(AI_CONFIG_PP_SBP_REMOVE, aiPrimitiveType_LINE | aiPrimitiveType_POINT); //Drop all primitives that aren't triangles
		const aiScene* scene = importer.ReadFile(fileName, aiProcessPreset_TargetRealtime_Quality);
		if (!scene) {
			log.error("Scene not imported: "+fileName);
		}
		log.error(importer.GetErrorString());
		return scene;
	}

}
<|endoftext|>


<commit_before>/*
***************************************
*   Asylum3D @ 2014-12-11
***************************************
*/

#ifndef __CRH3D9_MTL_WF_HPP__
#define __CRH3D9_MTL_WF_HPP__

/* Asylum Namespace */
namespace asy {

/******************/
/* Wavefront Mesh */
/******************/
class crh3d9_mesh_wf : public asylum
{
private:
    sD3D9_MAIN*         m_main;
    sD3D9_MESH*         m_mesh;
    const sD3D9_CALL*   m_call;

public:
    /* ==================================================================== */
    bool init2_ss (const crh3d9_main* main, const sWAVEFRONT* obj, leng_t idx)
    {
        leng_t  nv, ni;

        nv = wfront_gen_mesh2(NULL, NULL, NULL, 0, 0, 0, NULL, &ni, obj, idx);
        if (nv == 0)
            return (false);

        void_t* vb;
        void_t* ib;
        leng_t  bpv;

        bpv = sizeof(vec3d_t);
        if (obj->p_f[0].idx[2] != 0)
            bpv += sizeof(vec3d_t);
        if (obj->p_f[0].idx[1] != 0)
            bpv += sizeof(vec2d_t);
        vb = mem_calloc(nv, bpv);
        if (vb == NULL)
            return (false);
        if (nv > 65536)
            ib = mem_calloc(ni, sizeof(int32u));
        else
            ib = mem_calloc(ni, sizeof(int16u));
        if (ib == NULL) {
            mem_free(vb);
            return (false);
        }

        uint_t      fvf;
        vec3d_t*    xyz;
        vec3d_t*    nrm;
        vec2d_t*    uvw;

        fvf = D3DFVF_XYZ;
        xyz = (vec3d_t*)vb;
        if (obj->p_f[0].idx[2] != 0) {
            fvf |= D3DFVF_NORMAL;
            nrm = xyz + 1;
            uvw = (vec2d_t*)(nrm + 1);
        }
        else {
            nrm = NULL;
            uvw = (vec2d_t*)(xyz + 1);
        }
        if (obj->p_f[0].idx[1] != 0)
            fvf |= D3DFVF_TEX1;
        else
            uvw = NULL;
        wfront_gen_mesh2(xyz, nrm, uvw, bpv, 0, 0, ib, NULL, obj, idx);
        m_main = main->get_main();
        m_call = main->get_call();
        m_mesh = m_call->create_mesh_vib(m_main, nv, bpv, ni, D3DPOOL_MANAGED, D3DUSAGE_WRITEONLY,
                                         D3DPOOL_MANAGED, D3DUSAGE_WRITEONLY, fvf, vb, ib);
        mem_free(vb);
        mem_free(ib);
        if (m_mesh == NULL)
            return (false);
        return (true);
    }

    /* ================ */
    void apply_ss () const
    {
#if defined(ASY_USE_FIXED_3D)
        m_main->dev->SetFVF(m_mesh->fvf);
#endif
        m_main->dev->SetStreamSource(0, m_mesh->vbuf, 0, m_mesh->nbpv);
        m_main->dev->SetIndices(m_mesh->ibuf);
        m_main->dev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, m_mesh->vnum, 0, m_mesh->ntri);
    }
};

/***********************/
/* Wavefront Attribute */
/***********************/
class crh3d9_attr_wf : public asylum
{
private:
    D3DMATERIAL9    m_mtl;
    crh3d9_texr*    m_map_kd;
#if !defined(ASY_USE_FIXED_3D)
    crh3d9_texr*    m_map_ka;
    crh3d9_texr*    m_map_ks;
    crh3d9_texr*    m_map_ns;
    crh3d9_texr*    m_bump;
#endif
    sD3D9_MAIN*     m_main;

public:
    /* =========================================================================================== */
    bool init (const crh3d9_main* main, const sWAVEFRONT_M* mtl, const map_acs<crh3d9_texr>* texpool)
    {
        if (mtl->map_kd != NULL) {
            m_map_kd = texpool->get(mtl->map_kd);
            if (m_map_kd == NULL)
                return (false);
        }
        else {
            m_map_kd = NULL;
        }
        m_mtl.Diffuse.r = mtl->kd.x;
        m_mtl.Diffuse.g = mtl->kd.y;
        m_mtl.Diffuse.b = mtl->kd.z;
        m_mtl.Diffuse.a = mtl->d;
        if (m_mtl.Diffuse.a < 0.0f)
            m_mtl.Diffuse.a = 0.0f;
        else
        if (m_mtl.Diffuse.a > 1.0f)
            m_mtl.Diffuse.a = 1.0f;
        m_mtl.Ambient.r = mtl->ka.x;
        m_mtl.Ambient.g = mtl->ka.y;
        m_mtl.Ambient.b = mtl->ka.z;
        m_mtl.Ambient.a = 0.0f;
        m_mtl.Specular.r = mtl->ks.x;
        m_mtl.Specular.g = mtl->ks.y;
        m_mtl.Specular.b = mtl->ks.z;
#if defined(ASY_USE_FIXED_3D)
        m_mtl.Specular.a = 0.0f;
        m_mtl.Emissive.r = 0.0f;
        m_mtl.Emissive.g = 0.0f;
        m_mtl.Emissive.b = 0.0f;
        m_mtl.Emissive.a = 0.0f;
        m_mtl.Power = mtl->ns;
#else
        m_mtl.Specular.a = mtl->ns;
        m_mtl.Emissive.r = mtl->tf.x;
        m_mtl.Emissive.g = mtl->tf.y;
        m_mtl.Emissive.b = mtl->tf.z;
        m_mtl.Emissive.a = 1.0f;
        if (mtl->map_ka != NULL) {
            m_map_ka = texpool->get(mtl->map_ka);
            if (m_map_ka == NULL)
                return (false);
        }
        else {
            m_map_ka = NULL;
        }
        if (mtl->map_ks != NULL) {
            m_map_ks = texpool->get(mtl->map_ks);
            if (m_map_ks == NULL)
                return (false);
        }
        else {
            m_map_ks = NULL;
        }
        if (mtl->map_ns != NULL) {
            m_map_ns = texpool->get(mtl->map_ns);
            if (m_map_ns == NULL)
                return (false);
        }
        else {
            m_map_ns = NULL;
        }
        if (mtl->bump != NULL) {
            m_bump = texpool->get(mtl->bump);
            if (m_bump == NULL)
                return (false);
        }
        else {
            m_bump = NULL;
        }
#endif
        m_main = main->get_main();
        return (true);
    }

    /* ============= */
    bool order () const
    {
        return ((m_mtl.Diffuse.a < 1.0f) ? true : false);
    }

    /* ================ */
    void apply_ff () const
    {
        if (m_map_kd != NULL)
            m_map_kd->apply(0);
        else
            m_main->dev->SetTexture(0, NULL);
        m_main->dev->SetMaterial(&m_mtl);
    }
};

}   /* namespace */

#endif  /* __CRH3D9_MTL_WF_HPP__ */
<commit_msg>Asylum: 添加 WAVEFRONT OBJ 材质的实现<commit_after>/*
***************************************
*   Asylum3D @ 2014-12-11
***************************************
*/

#ifndef __CRH3D9_MTL_WF_HPP__
#define __CRH3D9_MTL_WF_HPP__

/* Asylum Namespace */
namespace asy {

/******************/
/* Wavefront Mesh */
/******************/
class crh3d9_mesh_wf : public asylum
{
private:
    sD3D9_MAIN*         m_main;
    sD3D9_MESH*         m_mesh;
    const sD3D9_CALL*   m_call;

public:
    /* ==================================================================== */
    bool init2_ss (const crh3d9_main* main, const sWAVEFRONT* obj, leng_t idx)
    {
        leng_t  nv, ni;

        nv = wfront_gen_mesh2(NULL, NULL, NULL, 0, 0, 0, NULL, &ni, obj, idx);
        if (nv == 0)
            return (false);

        void_t* vb;
        void_t* ib;
        leng_t  bpv;

        bpv = sizeof(vec3d_t);
        if (obj->p_f[0].idx[2] != 0)
            bpv += sizeof(vec3d_t);
        if (obj->p_f[0].idx[1] != 0)
            bpv += sizeof(vec2d_t);
        vb = mem_calloc(nv, bpv);
        if (vb == NULL)
            return (false);
        if (nv > 65536)
            ib = mem_calloc(ni, sizeof(int32u));
        else
            ib = mem_calloc(ni, sizeof(int16u));
        if (ib == NULL) {
            mem_free(vb);
            return (false);
        }

        uint_t      fvf;
        vec3d_t*    xyz;
        vec3d_t*    nrm;
        vec2d_t*    uvw;

        fvf = D3DFVF_XYZ;
        xyz = (vec3d_t*)vb;
        if (obj->p_f[0].idx[2] != 0) {
            fvf |= D3DFVF_NORMAL;
            nrm = xyz + 1;
            uvw = (vec2d_t*)(nrm + 1);
        }
        else {
            nrm = NULL;
            uvw = (vec2d_t*)(xyz + 1);
        }
        if (obj->p_f[0].idx[1] != 0)
            fvf |= D3DFVF_TEX1;
        else
            uvw = NULL;
        wfront_gen_mesh2(xyz, nrm, uvw, bpv, 0, 0, ib, NULL, obj, idx);
        m_main = main->get_main();
        m_call = main->get_call();
        m_mesh = m_call->create_mesh_vib(m_main, nv, bpv, ni, D3DPOOL_MANAGED, D3DUSAGE_WRITEONLY,
                                         D3DPOOL_MANAGED, D3DUSAGE_WRITEONLY, fvf, vb, ib);
        mem_free(vb);
        mem_free(ib);
        if (m_mesh == NULL)
            return (false);
        return (true);
    }

    /* ====== */
    void free ()
    {
        m_call->release_mesh(m_mesh);
    }

    /* ================ */
    void apply_ss () const
    {
#if defined(ASY_USE_FIXED_3D)
        m_main->dev->SetFVF(m_mesh->fvf);
#endif
        m_main->dev->SetStreamSource(0, m_mesh->vbuf, 0, m_mesh->nbpv);
        m_main->dev->SetIndices(m_mesh->ibuf);
        m_main->dev->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, m_mesh->vnum, 0, m_mesh->ntri);
    }
};

/***********************/
/* Wavefront Attribute */
/***********************/
class crh3d9_attr_wf : public asylum
{
private:
    D3DMATERIAL9    m_mtl;
    crh3d9_texr*    m_map_kd;
#if !defined(ASY_USE_FIXED_3D)
    crh3d9_texr*    m_map_ka;
    crh3d9_texr*    m_map_ks;
    crh3d9_texr*    m_map_ns;
    crh3d9_texr*    m_bump;
#endif
    sD3D9_MAIN*     m_main;

public:
    /* =========================================================================================== */
    bool init (const crh3d9_main* main, const sWAVEFRONT_M* mtl, const map_acs<crh3d9_texr>* texpool)
    {
        if (mtl->map_kd != NULL) {
            m_map_kd = texpool->get(mtl->map_kd);
            if (m_map_kd == NULL)
                return (false);
        }
        else {
            m_map_kd = NULL;
        }
        m_mtl.Diffuse.r = mtl->kd.x;
        m_mtl.Diffuse.g = mtl->kd.y;
        m_mtl.Diffuse.b = mtl->kd.z;
        m_mtl.Diffuse.a = mtl->d;
        if (m_mtl.Diffuse.a < 0.0f)
            m_mtl.Diffuse.a = 0.0f;
        else
        if (m_mtl.Diffuse.a > 1.0f)
            m_mtl.Diffuse.a = 1.0f;
        m_mtl.Ambient.r = mtl->ka.x;
        m_mtl.Ambient.g = mtl->ka.y;
        m_mtl.Ambient.b = mtl->ka.z;
        m_mtl.Ambient.a = 0.0f;
        m_mtl.Specular.r = mtl->ks.x;
        m_mtl.Specular.g = mtl->ks.y;
        m_mtl.Specular.b = mtl->ks.z;
#if defined(ASY_USE_FIXED_3D)
        m_mtl.Specular.a = 0.0f;
        m_mtl.Emissive.r = 0.0f;
        m_mtl.Emissive.g = 0.0f;
        m_mtl.Emissive.b = 0.0f;
        m_mtl.Emissive.a = 0.0f;
        m_mtl.Power = mtl->ns;
#else
        m_mtl.Specular.a = mtl->ns;
        m_mtl.Emissive.r = mtl->tf.x;
        m_mtl.Emissive.g = mtl->tf.y;
        m_mtl.Emissive.b = mtl->tf.z;
        m_mtl.Emissive.a = 1.0f;
        if (mtl->map_ka != NULL) {
            m_map_ka = texpool->get(mtl->map_ka);
            if (m_map_ka == NULL)
                return (false);
        }
        else {
            m_map_ka = NULL;
        }
        if (mtl->map_ks != NULL) {
            m_map_ks = texpool->get(mtl->map_ks);
            if (m_map_ks == NULL)
                return (false);
        }
        else {
            m_map_ks = NULL;
        }
        if (mtl->map_ns != NULL) {
            m_map_ns = texpool->get(mtl->map_ns);
            if (m_map_ns == NULL)
                return (false);
        }
        else {
            m_map_ns = NULL;
        }
        if (mtl->bump != NULL) {
            m_bump = texpool->get(mtl->bump);
            if (m_bump == NULL)
                return (false);
        }
        else {
            m_bump = NULL;
        }
#endif
        m_main = main->get_main();
        return (true);
    }

    /* ============= */
    bool order () const
    {
        return ((m_mtl.Diffuse.a < 1.0f) ? true : false);
    }

    /* ================ */
    void apply_ff () const
    {
        if (m_map_kd != NULL)
            m_map_kd->apply(0);
        else
            m_main->dev->SetTexture(0, NULL);
        m_main->dev->SetMaterial(&m_mtl);
    }
};

/******************************/
/* Wavefront Material (Fixed) */
/******************************/
class crh3d9_mtl_wf_fixed : public material_i
{
private:
    leng_t          m_anow;
    sWAVEFRONT*     m_objs;
    crh3d9_mesh_wf* m_mesh;
    crh3d9_attr_wf* m_attr;

public:
    /* ============================================================================ */
    crh3d9_mtl_wf_fixed (sWAVEFRONT* objs, crh3d9_mesh_wf* mesh, crh3d9_attr_wf* attr)
    {
        m_anow = 0;
        m_objs = objs;
        m_mesh = mesh;
        m_attr = attr;
    }

    /* ========================= */
    virtual ~crh3d9_mtl_wf_fixed ()
    {
        wfront_obj_free(m_objs);
        for (leng_t idx = 0; idx < m_objs->n_g; idx++)
            m_mesh[idx].free();
        mem_free(m_mesh);
        mem_free(m_attr);
    }

public:
    /* ================ */
    virtual void commit ()
    {
        leng_t  aidx;

        for (leng_t idx = 0; idx < m_objs->n_g; idx++) {
            aidx = m_objs->p_g[idx].attr;
            if (aidx == 0)
                return;
            if (m_anow != aidx) {
                m_anow = aidx;
                m_attr[aidx - 1].apply_ff();
            }
            m_mesh[idx].apply_ss();
        }
    }
};

}   /* namespace */

#endif  /* __CRH3D9_MTL_WF_HPP__ */
<|endoftext|>


<commit_before>#include "input.h"

InputHandler::InputHandler(sf::Window* Window, Player* Player, Renderer* Renderer) : app(Window), player(Player), renderer(Renderer) {
    app->ShowMouseCursor(false);
}

bool fullscreen = false;
void InputHandler::handleEvent(sf::Event Event) {
    // Close window : exit
    if (Event.Type == sf::Event::Closed)
        app->Close();

    if(Event.Type == sf::Event::KeyPressed) {
        switch(Event.Key.Code) {
            // Escape key : exit
            case sf::Key::Escape:
                app->Close();
                break;
/*            // Spacebar : jump
            case sf::Key::Space:
                player->Jump();
                break;*/
            // F5 : regenerate terrain
            case sf::Key::F5:
                renderer->terrain.Regenerate();
                break;
            // F11 : toggle fullscreen
            case sf::Key::F11:
                toggleFullscreen();
                break;
        }
    }

    // Resize event : adjust viewport
    if (Event.Type == sf::Event::Resized)
        glViewport(0, 0, Event.Size.Width, Event.Size.Height);
}

float ElapsedTime;
float mouseDeltaX, mouseDeltaY;

void InputHandler::handleEvents() {
    const sf::Input& Input = app->GetInput();

    // Constant movement speed
    ElapsedTime = Clock.GetElapsedTime();
    Clock.Reset();

    // Handle held keys
    if (Input.IsKeyDown(sf::Key::S))     player->Forward(-ElapsedTime);
    if (Input.IsKeyDown(sf::Key::W))     player->Forward( ElapsedTime);
    if (Input.IsKeyDown(sf::Key::D))     player->Strafe(-ElapsedTime);
    if (Input.IsKeyDown(sf::Key::A))     player->Strafe( ElapsedTime);
    if (Input.IsKeyDown(sf::Key::Z))     player->Speed++;
    if (Input.IsKeyDown(sf::Key::X))     player->Speed--;
    if (Input.IsKeyDown(sf::Key::Space)) player->Jump();

    // Handle other events
    sf::Event Event;
    while (app->GetEvent(Event))
    {
        handleEvent(Event);
    }

    // Rotate view based on mouse movement
    mouseDeltaX = Input.GetMouseX() - 100;
    mouseDeltaY = Input.GetMouseY() - 100;
    app->SetCursorPosition(100, 100);

    if (!(mouseDeltaX == -100 && mouseDeltaY == -100) && !(mouseDeltaX == 0 && mouseDeltaY == 0))
        player->ChangeRotation((mouseDeltaY/10), (mouseDeltaX/10));

    player->DoStep(ElapsedTime);
}

void InputHandler::toggleFullscreen() {
    fullscreen = !fullscreen;
    app->Create(sf::VideoMode(800, 600, 32), "MineCube", (fullscreen ? sf::Style::Fullscreen : sf::Style::Resize|sf::Style::Close));

    renderer->InitGraphics();
    app->ShowMouseCursor(false);
}
<commit_msg>Woops. Removed old commented out code.<commit_after>#include "input.h"

InputHandler::InputHandler(sf::Window* Window, Player* Player, Renderer* Renderer) : app(Window), player(Player), renderer(Renderer) {
    app->ShowMouseCursor(false);
}

bool fullscreen = false;
void InputHandler::handleEvent(sf::Event Event) {
    // Close window : exit
    if (Event.Type == sf::Event::Closed)
        app->Close();

    if(Event.Type == sf::Event::KeyPressed) {
        switch(Event.Key.Code) {
            // Escape key : exit
            case sf::Key::Escape:
                app->Close();
                break;
            // F5 : regenerate terrain
            case sf::Key::F5:
                renderer->terrain.Regenerate();
                break;
            // F11 : toggle fullscreen
            case sf::Key::F11:
                toggleFullscreen();
                break;
        }
    }

    // Resize event : adjust viewport
    if (Event.Type == sf::Event::Resized)
        glViewport(0, 0, Event.Size.Width, Event.Size.Height);
}

float ElapsedTime;
float mouseDeltaX, mouseDeltaY;

void InputHandler::handleEvents() {
    const sf::Input& Input = app->GetInput();

    // Constant movement speed
    ElapsedTime = Clock.GetElapsedTime();
    Clock.Reset();

    // Handle held keys
    if (Input.IsKeyDown(sf::Key::S))     player->Forward(-ElapsedTime);
    if (Input.IsKeyDown(sf::Key::W))     player->Forward( ElapsedTime);
    if (Input.IsKeyDown(sf::Key::D))     player->Strafe(-ElapsedTime);
    if (Input.IsKeyDown(sf::Key::A))     player->Strafe( ElapsedTime);
    if (Input.IsKeyDown(sf::Key::Z))     player->Speed++;
    if (Input.IsKeyDown(sf::Key::X))     player->Speed--;
    if (Input.IsKeyDown(sf::Key::Space)) player->Jump();

    // Handle other events
    sf::Event Event;
    while (app->GetEvent(Event))
    {
        handleEvent(Event);
    }

    // Rotate view based on mouse movement
    mouseDeltaX = Input.GetMouseX() - 100;
    mouseDeltaY = Input.GetMouseY() - 100;
    app->SetCursorPosition(100, 100);

    if (!(mouseDeltaX == -100 && mouseDeltaY == -100) && !(mouseDeltaX == 0 && mouseDeltaY == 0))
        player->ChangeRotation((mouseDeltaY/10), (mouseDeltaX/10));

    player->DoStep(ElapsedTime);
}

void InputHandler::toggleFullscreen() {
    fullscreen = !fullscreen;
    app->Create(sf::VideoMode(800, 600, 32), "MineCube", (fullscreen ? sf::Style::Fullscreen : sf::Style::Resize|sf::Style::Close));

    renderer->InitGraphics();
    app->ShowMouseCursor(false);
}
<|endoftext|>