<commit_before>// Interface for 2D Canvas element
//
// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
//
// 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA

#include "CanvasElement.hxx"
#include <simgear/canvas/Canvas.hxx>
#include <simgear/canvas/CanvasEventListener.hxx>
#include <simgear/canvas/CanvasEventVisitor.hxx>
#include <simgear/canvas/MouseEvent.hxx>
#include <simgear/scene/material/parseBlendFunc.hxx>

#include <osg/Drawable>
#include <osg/Geode>
#include <osg/Scissor>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
#include <boost/tokenizer.hpp>

#include <cassert>
#include <cstring>

namespace simgear
{
namespace canvas
{
  const std::string NAME_TRANSFORM = "tf";

  //----------------------------------------------------------------------------
  Element::OSGUserData::OSGUserData(ElementPtr element):
    element(element)
  {

  }

  //----------------------------------------------------------------------------
  Element::~Element()
  {

  }

  //----------------------------------------------------------------------------
  void Element::setSelf(const PropertyBasedElementPtr& self)
  {
    PropertyBasedElement::setSelf(self);

    _transform->setUserData
    (
      new OSGUserData(boost::static_pointer_cast<Element>(self))
    );
  }

  //----------------------------------------------------------------------------
  void Element::onDestroy()
  {
    if( !_transform.valid() )
      return;

    // The transform node keeps a reference on this element, so ensure it is
    // deleted.
    BOOST_FOREACH(osg::Group* parent, _transform->getParents())
    {
      parent->removeChild(_transform.get());
    }
  }

  //----------------------------------------------------------------------------
  ElementWeakPtr Element::getWeakPtr() const
  {
    return boost::static_pointer_cast<Element>(_self.lock());
  }

  //----------------------------------------------------------------------------
  void Element::update(double dt)
  {
    if( !_transform->getNodeMask() )
      // Don't do anything if element is hidden
      return;

    if( _transform_dirty )
    {
      osg::Matrix m;
      for( size_t i = 0; i < _transform_types.size(); ++i )
      {
        // Skip unused indizes...
        if( _transform_types[i] == TT_NONE )
          continue;

        SGPropertyNode* tf_node = _node->getChild("tf", i, true);

        // Build up the matrix representation of the current transform node
        osg::Matrix tf;
        switch( _transform_types[i] )
        {
          case TT_MATRIX:
            tf = osg::Matrix( tf_node->getDoubleValue("m[0]", 1),
                              tf_node->getDoubleValue("m[1]", 0),
                              0,
                              tf_node->getDoubleValue("m[6]", 0),

                              tf_node->getDoubleValue("m[2]", 0),
                              tf_node->getDoubleValue("m[3]", 1),
                              0,
                              tf_node->getDoubleValue("m[7]", 0),

                              0,
                              0,
                              1,
                              0,

                              tf_node->getDoubleValue("m[4]", 0),
                              tf_node->getDoubleValue("m[5]", 0),
                              0,
                              tf_node->getDoubleValue("m[8]", 1) );
            break;
          case TT_TRANSLATE:
            tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("t[0]", 0),
                                          tf_node->getDoubleValue("t[1]", 0),
                                          0 ) );
            break;
          case TT_ROTATE:
            tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
            break;
          case TT_SCALE:
          {
            float sx = tf_node->getDoubleValue("s[0]", 1);
            // sy defaults to sx...
            tf.makeScale( sx, tf_node->getDoubleValue("s[1]", sx), 1 );
            break;
          }
          default:
            break;
        }
        m.postMult( tf );
      }
      _transform->setMatrix(m);
      _transform_dirty = false;
    }

    // Update bounding box on manual update (manual updates pass zero dt)
    if( dt == 0 && _drawable )
      _drawable->getBound();

    if( _attributes_dirty & BLEND_FUNC )
    {
      parseBlendFunc(
        _transform->getOrCreateStateSet(),
        _node->getChild("blend-source"),
        _node->getChild("blend-destination"),
        _node->getChild("blend-source-rgb"),
        _node->getChild("blend-destination-rgb"),
        _node->getChild("blend-source-alpha"),
        _node->getChild("blend-destination-alpha")
      );
      _attributes_dirty &= ~BLEND_FUNC;
    }
  }

  //----------------------------------------------------------------------------
  naRef Element::addEventListener(const nasal::CallContext& ctx)
  {
    const std::string type_str = ctx.requireArg<std::string>(0);
    naRef code = ctx.requireArg<naRef>(1);

    SG_LOG
    (
      SG_NASAL,
      SG_INFO,
      "addEventListener(" << _node->getPath() << ", " << type_str << ")"
    );

    Event::Type type = Event::strToType(type_str);
    if( type == Event::UNKNOWN )
      naRuntimeError( ctx.c,
                      "addEventListener: Unknown event type %s",
                      type_str.c_str() );

    _listener[ type ].push_back
    (
      boost::make_shared<EventListener>( code,
                                         _canvas.lock()->getSystemAdapter() )
    );

    return naNil();
  }

  //----------------------------------------------------------------------------
  void Element::clearEventListener()
  {
    _listener.clear();
  }

  //----------------------------------------------------------------------------
  bool Element::accept(EventVisitor& visitor)
  {
    if( !_transform.valid() )
      return false;

    return visitor.apply(*this);
  }

  //----------------------------------------------------------------------------
  bool Element::ascend(EventVisitor& visitor)
  {
    if( _parent )
      return _parent->accept(visitor);
    return true;
  }

  //----------------------------------------------------------------------------
  bool Element::traverse(EventVisitor& visitor)
  {
    return true;
  }

  //----------------------------------------------------------------------------
  bool Element::handleEvent(canvas::EventPtr event)
  {
    ListenerMap::iterator listeners = _listener.find(event->getType());
    if( listeners == _listener.end() )
      return false;

    BOOST_FOREACH(EventListenerPtr listener, listeners->second)
      listener->call(event);

    return true;
  }

  //----------------------------------------------------------------------------
  bool Element::hitBound( const osg::Vec2f& pos,
                          const osg::Vec2f& local_pos ) const
  {
    const osg::Vec3f pos3(pos, 0);

    // Drawables have a bounding box...
    if( _drawable )
      return _drawable->getBound().contains(osg::Vec3f(local_pos, 0));
    // ... for other elements, i.e. groups only a bounding sphere is available
    else
      return _transform->getBound().contains(osg::Vec3f(pos, 0));
  }

  //----------------------------------------------------------------------------
  bool Element::isVisible() const
  {
    return _transform->getNodeMask() != 0;
  }

  //----------------------------------------------------------------------------
  osg::MatrixTransform* Element::getMatrixTransform()
  {
    return _transform.get();
  }

  //----------------------------------------------------------------------------
  osg::MatrixTransform const* Element::getMatrixTransform() const
  {
    return _transform.get();
  }

  //----------------------------------------------------------------------------
  void Element::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
  {
    if(    parent == _node
        && child->getNameString() == NAME_TRANSFORM )
    {
      if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
        _transform_types.resize( child->getIndex() + 1 );

      _transform_types[ child->getIndex() ] = TT_NONE;
      _transform_dirty = true;
      return;
    }
    else if(    parent->getParent() == _node
             && parent->getNameString() == NAME_TRANSFORM )
    {
      assert(parent->getIndex() < static_cast<int>(_transform_types.size()));

      const std::string& name = child->getNameString();

      TransformType& type = _transform_types[parent->getIndex()];

      if(      name == "m" )
        type = TT_MATRIX;
      else if( name == "t" )
        type = TT_TRANSLATE;
      else if( name == "rot" )
        type = TT_ROTATE;
      else if( name == "s" )
        type = TT_SCALE;

      _transform_dirty = true;
      return;
    }

    childAdded(child);
  }

  //----------------------------------------------------------------------------
  void Element::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
  {
    if( parent == _node && child->getNameString() == NAME_TRANSFORM )
    {
      if( !_transform.valid() )
        return;

      if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
      {
        SG_LOG
        (
          SG_GENERAL,
          SG_WARN,
          "Element::childRemoved: unknown transform: " << child->getPath()
        );
        return;
      }

      _transform_types[ child->getIndex() ] = TT_NONE;

      while( !_transform_types.empty() && _transform_types.back() == TT_NONE )
        _transform_types.pop_back();

      _transform_dirty = true;
      return;
    }

    childRemoved(child);
  }

  //----------------------------------------------------------------------------
  void Element::valueChanged(SGPropertyNode* child)
  {
    SGPropertyNode *parent = child->getParent();
    if( parent == _node )
    {
      const std::string& name = child->getNameString();
      if( setStyle(child) )
        return;
      else if( name == "update" )
        return update(0);
      else if( name == "visible" )
        // TODO check if we need another nodemask
        return _transform->setNodeMask( child->getBoolValue() ? 0xffffffff : 0 );
      else if( boost::starts_with(name, "blend-") )
        return (void)(_attributes_dirty |= BLEND_FUNC);
    }
    else if(   parent->getParent() == _node
            && parent->getNameString() == NAME_TRANSFORM )
    {
      _transform_dirty = true;
      return;
    }

    childChanged(child);
  }

  //----------------------------------------------------------------------------
  bool Element::setStyle(const SGPropertyNode* child)
  {
    StyleSetters::const_iterator setter =
      _style_setters.find(child->getNameString());
    if( setter == _style_setters.end() )
      return false;

    const StyleSetter* style_setter = &setter->second.setter;
    while( style_setter )
    {
      if( style_setter->func(*this, child) )
        return true;
      style_setter = style_setter->next;
    }
    return false;
  }

  //----------------------------------------------------------------------------
  void Element::setClip(const std::string& clip)
  {
    if( clip.empty() || clip == "auto" )
    {
      getOrCreateStateSet()->removeAttribute(osg::StateAttribute::SCISSOR);
      return;
    }

    // TODO generalize CSS property parsing
    const std::string RECT("rect(");
    if(    !boost::ends_with(clip, ")")
        || !boost::starts_with(clip, RECT) )
    {
      SG_LOG(SG_GENERAL, SG_WARN, "Canvas: invalid clip: " << clip);
      return;
    }

    typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
    const boost::char_separator<char> del(", \t\npx");

    tokenizer tokens(clip.begin() + RECT.size(), clip.end() - 1, del);
    int comp = 0;
    int values[4];
    for( tokenizer::const_iterator tok = tokens.begin();
         tok != tokens.end() && comp < 4;
         ++tok, ++comp )
    {
      values[comp] = boost::lexical_cast<int>(*tok);
    }

    if( comp < 4 )
    {
      SG_LOG(SG_GENERAL, SG_WARN, "Canvas: invalid clip: " << clip);
      return;
    }

    float scale_x = 1,
          scale_y = 1;

    CanvasPtr canvas = _canvas.lock();
    if( canvas )
    {
      // The scissor rectangle isn't affected by any transformation, so we need
      // to convert to image/canvas coordinates on our selves.
      scale_x = canvas->getSizeX()
              / static_cast<float>(canvas->getViewWidth());
      scale_y = canvas->getSizeY()
              / static_cast<float>(canvas->getViewHeight());
    }

    osg::Scissor* scissor = new osg::Scissor();
    // <top>, <right>, <bottom>, <left>
    scissor->x() = scale_x * values[3];
    scissor->y() = scale_y * values[0];
    scissor->width() = scale_x * (values[1] - values[3]);
    scissor->height() = scale_y * (values[2] - values[0]);

    if( canvas )
      // Canvas has y axis upside down
      scissor->y() = canvas->getSizeY() - scissor->y() - scissor->height();

    getOrCreateStateSet()->setAttributeAndModes(scissor);
  }

  //----------------------------------------------------------------------------
  void Element::setBoundingBox(const osg::BoundingBox& bb)
  {
    if( _bounding_box.empty() )
    {
      SGPropertyNode* bb_node = _node->getChild("bounding-box", 0, true);
      _bounding_box.resize(4);
      _bounding_box[0] = bb_node->getChild("min-x", 0, true);
      _bounding_box[1] = bb_node->getChild("min-y", 0, true);
      _bounding_box[2] = bb_node->getChild("max-x", 0, true);
      _bounding_box[3] = bb_node->getChild("max-y", 0, true);
    }

    _bounding_box[0]->setFloatValue(bb._min.x());
    _bounding_box[1]->setFloatValue(bb._min.y());
    _bounding_box[2]->setFloatValue(bb._max.x());
    _bounding_box[3]->setFloatValue(bb._max.y());
  }

  //----------------------------------------------------------------------------
  osg::BoundingBox Element::getTransformedBounds(const osg::Matrix& m) const
  {
    if( !_drawable )
      return osg::BoundingBox();

    osg::BoundingBox transformed;
    const osg::BoundingBox& bb = _drawable->getBound();
    for(int i = 0; i < 4; ++i)
      transformed.expandBy( m * bb.corner(i) );

    return transformed;
  }

  //----------------------------------------------------------------------------
  Element::StyleSetters Element::_style_setters;

  //----------------------------------------------------------------------------
  Element::Element( const CanvasWeakPtr& canvas,
                    const SGPropertyNode_ptr& node,
                    const Style& parent_style,
                    Element* parent ):
    PropertyBasedElement(node),
    _canvas( canvas ),
    _parent( parent ),
    _attributes_dirty( 0 ),
    _transform_dirty( false ),
    _transform( new osg::MatrixTransform ),
    _style( parent_style ),
    _drawable( 0 )
  {
    SG_LOG
    (
      SG_GL,
      SG_DEBUG,
      "New canvas element " << node->getPath()
    );

    if( !isInit<Element>() )
    {
      addStyle("clip", "", &Element::setClip);
    }
  }

  //----------------------------------------------------------------------------
  void Element::setDrawable( osg::Drawable* drawable )
  {
    _drawable = drawable;
    assert( _drawable );

    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(_drawable);
    _transform->addChild(geode);
  }

  //----------------------------------------------------------------------------
  osg::StateSet* Element::getOrCreateStateSet()
  {
    return _drawable ? _drawable->getOrCreateStateSet()
                     : _transform->getOrCreateStateSet();
  }

  //----------------------------------------------------------------------------
  void Element::setupStyle()
  {
    BOOST_FOREACH( Style::value_type style, _style )
      setStyle(style.second);
  }

} // namespace canvas
} // namespace simgear
<commit_msg>Canvas: Ignore hidden element on event traversal.<commit_after>// Interface for 2D Canvas element
//
// Copyright (C) 2012  Thomas Geymayer <tomgey@gmail.com>
//
// 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301, USA

#include "CanvasElement.hxx"
#include <simgear/canvas/Canvas.hxx>
#include <simgear/canvas/CanvasEventListener.hxx>
#include <simgear/canvas/CanvasEventVisitor.hxx>
#include <simgear/canvas/MouseEvent.hxx>
#include <simgear/scene/material/parseBlendFunc.hxx>

#include <osg/Drawable>
#include <osg/Geode>
#include <osg/Scissor>

#include <boost/algorithm/string/predicate.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/make_shared.hpp>
#include <boost/tokenizer.hpp>

#include <cassert>
#include <cstring>

namespace simgear
{
namespace canvas
{
  const std::string NAME_TRANSFORM = "tf";

  //----------------------------------------------------------------------------
  Element::OSGUserData::OSGUserData(ElementPtr element):
    element(element)
  {

  }

  //----------------------------------------------------------------------------
  Element::~Element()
  {

  }

  //----------------------------------------------------------------------------
  void Element::setSelf(const PropertyBasedElementPtr& self)
  {
    PropertyBasedElement::setSelf(self);

    _transform->setUserData
    (
      new OSGUserData(boost::static_pointer_cast<Element>(self))
    );
  }

  //----------------------------------------------------------------------------
  void Element::onDestroy()
  {
    if( !_transform.valid() )
      return;

    // The transform node keeps a reference on this element, so ensure it is
    // deleted.
    BOOST_FOREACH(osg::Group* parent, _transform->getParents())
    {
      parent->removeChild(_transform.get());
    }
  }

  //----------------------------------------------------------------------------
  ElementWeakPtr Element::getWeakPtr() const
  {
    return boost::static_pointer_cast<Element>(_self.lock());
  }

  //----------------------------------------------------------------------------
  void Element::update(double dt)
  {
    if( !_transform->getNodeMask() )
      // Don't do anything if element is hidden
      return;

    if( _transform_dirty )
    {
      osg::Matrix m;
      for( size_t i = 0; i < _transform_types.size(); ++i )
      {
        // Skip unused indizes...
        if( _transform_types[i] == TT_NONE )
          continue;

        SGPropertyNode* tf_node = _node->getChild("tf", i, true);

        // Build up the matrix representation of the current transform node
        osg::Matrix tf;
        switch( _transform_types[i] )
        {
          case TT_MATRIX:
            tf = osg::Matrix( tf_node->getDoubleValue("m[0]", 1),
                              tf_node->getDoubleValue("m[1]", 0),
                              0,
                              tf_node->getDoubleValue("m[6]", 0),

                              tf_node->getDoubleValue("m[2]", 0),
                              tf_node->getDoubleValue("m[3]", 1),
                              0,
                              tf_node->getDoubleValue("m[7]", 0),

                              0,
                              0,
                              1,
                              0,

                              tf_node->getDoubleValue("m[4]", 0),
                              tf_node->getDoubleValue("m[5]", 0),
                              0,
                              tf_node->getDoubleValue("m[8]", 1) );
            break;
          case TT_TRANSLATE:
            tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("t[0]", 0),
                                          tf_node->getDoubleValue("t[1]", 0),
                                          0 ) );
            break;
          case TT_ROTATE:
            tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
            break;
          case TT_SCALE:
          {
            float sx = tf_node->getDoubleValue("s[0]", 1);
            // sy defaults to sx...
            tf.makeScale( sx, tf_node->getDoubleValue("s[1]", sx), 1 );
            break;
          }
          default:
            break;
        }
        m.postMult( tf );
      }
      _transform->setMatrix(m);
      _transform_dirty = false;
    }

    // Update bounding box on manual update (manual updates pass zero dt)
    if( dt == 0 && _drawable )
      _drawable->getBound();

    if( _attributes_dirty & BLEND_FUNC )
    {
      parseBlendFunc(
        _transform->getOrCreateStateSet(),
        _node->getChild("blend-source"),
        _node->getChild("blend-destination"),
        _node->getChild("blend-source-rgb"),
        _node->getChild("blend-destination-rgb"),
        _node->getChild("blend-source-alpha"),
        _node->getChild("blend-destination-alpha")
      );
      _attributes_dirty &= ~BLEND_FUNC;
    }
  }

  //----------------------------------------------------------------------------
  naRef Element::addEventListener(const nasal::CallContext& ctx)
  {
    const std::string type_str = ctx.requireArg<std::string>(0);
    naRef code = ctx.requireArg<naRef>(1);

    SG_LOG
    (
      SG_NASAL,
      SG_INFO,
      "addEventListener(" << _node->getPath() << ", " << type_str << ")"
    );

    Event::Type type = Event::strToType(type_str);
    if( type == Event::UNKNOWN )
      naRuntimeError( ctx.c,
                      "addEventListener: Unknown event type %s",
                      type_str.c_str() );

    _listener[ type ].push_back
    (
      boost::make_shared<EventListener>( code,
                                         _canvas.lock()->getSystemAdapter() )
    );

    return naNil();
  }

  //----------------------------------------------------------------------------
  void Element::clearEventListener()
  {
    _listener.clear();
  }

  //----------------------------------------------------------------------------
  bool Element::accept(EventVisitor& visitor)
  {
    if( !isVisible() )
      return false;

    return visitor.apply(*this);
  }

  //----------------------------------------------------------------------------
  bool Element::ascend(EventVisitor& visitor)
  {
    if( _parent )
      return _parent->accept(visitor);
    return true;
  }

  //----------------------------------------------------------------------------
  bool Element::traverse(EventVisitor& visitor)
  {
    return true;
  }

  //----------------------------------------------------------------------------
  bool Element::handleEvent(canvas::EventPtr event)
  {
    ListenerMap::iterator listeners = _listener.find(event->getType());
    if( listeners == _listener.end() )
      return false;

    BOOST_FOREACH(EventListenerPtr listener, listeners->second)
      listener->call(event);

    return true;
  }

  //----------------------------------------------------------------------------
  bool Element::hitBound( const osg::Vec2f& pos,
                          const osg::Vec2f& local_pos ) const
  {
    const osg::Vec3f pos3(pos, 0);

    // Drawables have a bounding box...
    if( _drawable )
      return _drawable->getBound().contains(osg::Vec3f(local_pos, 0));
    // ... for other elements, i.e. groups only a bounding sphere is available
    else
      return _transform->getBound().contains(osg::Vec3f(pos, 0));
  }

  //----------------------------------------------------------------------------
  bool Element::isVisible() const
  {
    return _transform.valid() && _transform->getNodeMask() != 0;
  }

  //----------------------------------------------------------------------------
  osg::MatrixTransform* Element::getMatrixTransform()
  {
    return _transform.get();
  }

  //----------------------------------------------------------------------------
  osg::MatrixTransform const* Element::getMatrixTransform() const
  {
    return _transform.get();
  }

  //----------------------------------------------------------------------------
  void Element::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
  {
    if(    parent == _node
        && child->getNameString() == NAME_TRANSFORM )
    {
      if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
        _transform_types.resize( child->getIndex() + 1 );

      _transform_types[ child->getIndex() ] = TT_NONE;
      _transform_dirty = true;
      return;
    }
    else if(    parent->getParent() == _node
             && parent->getNameString() == NAME_TRANSFORM )
    {
      assert(parent->getIndex() < static_cast<int>(_transform_types.size()));

      const std::string& name = child->getNameString();

      TransformType& type = _transform_types[parent->getIndex()];

      if(      name == "m" )
        type = TT_MATRIX;
      else if( name == "t" )
        type = TT_TRANSLATE;
      else if( name == "rot" )
        type = TT_ROTATE;
      else if( name == "s" )
        type = TT_SCALE;

      _transform_dirty = true;
      return;
    }

    childAdded(child);
  }

  //----------------------------------------------------------------------------
  void Element::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
  {
    if( parent == _node && child->getNameString() == NAME_TRANSFORM )
    {
      if( !_transform.valid() )
        return;

      if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
      {
        SG_LOG
        (
          SG_GENERAL,
          SG_WARN,
          "Element::childRemoved: unknown transform: " << child->getPath()
        );
        return;
      }

      _transform_types[ child->getIndex() ] = TT_NONE;

      while( !_transform_types.empty() && _transform_types.back() == TT_NONE )
        _transform_types.pop_back();

      _transform_dirty = true;
      return;
    }

    childRemoved(child);
  }

  //----------------------------------------------------------------------------
  void Element::valueChanged(SGPropertyNode* child)
  {
    SGPropertyNode *parent = child->getParent();
    if( parent == _node )
    {
      const std::string& name = child->getNameString();
      if( setStyle(child) )
        return;
      else if( name == "update" )
        return update(0);
      else if( name == "visible" )
        // TODO check if we need another nodemask
        return _transform->setNodeMask( child->getBoolValue() ? 0xffffffff : 0 );
      else if( boost::starts_with(name, "blend-") )
        return (void)(_attributes_dirty |= BLEND_FUNC);
    }
    else if(   parent->getParent() == _node
            && parent->getNameString() == NAME_TRANSFORM )
    {
      _transform_dirty = true;
      return;
    }

    childChanged(child);
  }

  //----------------------------------------------------------------------------
  bool Element::setStyle(const SGPropertyNode* child)
  {
    StyleSetters::const_iterator setter =
      _style_setters.find(child->getNameString());
    if( setter == _style_setters.end() )
      return false;

    const StyleSetter* style_setter = &setter->second.setter;
    while( style_setter )
    {
      if( style_setter->func(*this, child) )
        return true;
      style_setter = style_setter->next;
    }
    return false;
  }

  //----------------------------------------------------------------------------
  void Element::setClip(const std::string& clip)
  {
    if( clip.empty() || clip == "auto" )
    {
      getOrCreateStateSet()->removeAttribute(osg::StateAttribute::SCISSOR);
      return;
    }

    // TODO generalize CSS property parsing
    const std::string RECT("rect(");
    if(    !boost::ends_with(clip, ")")
        || !boost::starts_with(clip, RECT) )
    {
      SG_LOG(SG_GENERAL, SG_WARN, "Canvas: invalid clip: " << clip);
      return;
    }

    typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
    const boost::char_separator<char> del(", \t\npx");

    tokenizer tokens(clip.begin() + RECT.size(), clip.end() - 1, del);
    int comp = 0;
    int values[4];
    for( tokenizer::const_iterator tok = tokens.begin();
         tok != tokens.end() && comp < 4;
         ++tok, ++comp )
    {
      values[comp] = boost::lexical_cast<int>(*tok);
    }

    if( comp < 4 )
    {
      SG_LOG(SG_GENERAL, SG_WARN, "Canvas: invalid clip: " << clip);
      return;
    }

    float scale_x = 1,
          scale_y = 1;

    CanvasPtr canvas = _canvas.lock();
    if( canvas )
    {
      // The scissor rectangle isn't affected by any transformation, so we need
      // to convert to image/canvas coordinates on our selves.
      scale_x = canvas->getSizeX()
              / static_cast<float>(canvas->getViewWidth());
      scale_y = canvas->getSizeY()
              / static_cast<float>(canvas->getViewHeight());
    }

    osg::Scissor* scissor = new osg::Scissor();
    // <top>, <right>, <bottom>, <left>
    scissor->x() = scale_x * values[3];
    scissor->y() = scale_y * values[0];
    scissor->width() = scale_x * (values[1] - values[3]);
    scissor->height() = scale_y * (values[2] - values[0]);

    if( canvas )
      // Canvas has y axis upside down
      scissor->y() = canvas->getSizeY() - scissor->y() - scissor->height();

    getOrCreateStateSet()->setAttributeAndModes(scissor);
  }

  //----------------------------------------------------------------------------
  void Element::setBoundingBox(const osg::BoundingBox& bb)
  {
    if( _bounding_box.empty() )
    {
      SGPropertyNode* bb_node = _node->getChild("bounding-box", 0, true);
      _bounding_box.resize(4);
      _bounding_box[0] = bb_node->getChild("min-x", 0, true);
      _bounding_box[1] = bb_node->getChild("min-y", 0, true);
      _bounding_box[2] = bb_node->getChild("max-x", 0, true);
      _bounding_box[3] = bb_node->getChild("max-y", 0, true);
    }

    _bounding_box[0]->setFloatValue(bb._min.x());
    _bounding_box[1]->setFloatValue(bb._min.y());
    _bounding_box[2]->setFloatValue(bb._max.x());
    _bounding_box[3]->setFloatValue(bb._max.y());
  }

  //----------------------------------------------------------------------------
  osg::BoundingBox Element::getTransformedBounds(const osg::Matrix& m) const
  {
    if( !_drawable )
      return osg::BoundingBox();

    osg::BoundingBox transformed;
    const osg::BoundingBox& bb = _drawable->getBound();
    for(int i = 0; i < 4; ++i)
      transformed.expandBy( m * bb.corner(i) );

    return transformed;
  }

  //----------------------------------------------------------------------------
  Element::StyleSetters Element::_style_setters;

  //----------------------------------------------------------------------------
  Element::Element( const CanvasWeakPtr& canvas,
                    const SGPropertyNode_ptr& node,
                    const Style& parent_style,
                    Element* parent ):
    PropertyBasedElement(node),
    _canvas( canvas ),
    _parent( parent ),
    _attributes_dirty( 0 ),
    _transform_dirty( false ),
    _transform( new osg::MatrixTransform ),
    _style( parent_style ),
    _drawable( 0 )
  {
    SG_LOG
    (
      SG_GL,
      SG_DEBUG,
      "New canvas element " << node->getPath()
    );

    if( !isInit<Element>() )
    {
      addStyle("clip", "", &Element::setClip);
    }
  }

  //----------------------------------------------------------------------------
  void Element::setDrawable( osg::Drawable* drawable )
  {
    _drawable = drawable;
    assert( _drawable );

    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(_drawable);
    _transform->addChild(geode);
  }

  //----------------------------------------------------------------------------
  osg::StateSet* Element::getOrCreateStateSet()
  {
    return _drawable ? _drawable->getOrCreateStateSet()
                     : _transform->getOrCreateStateSet();
  }

  //----------------------------------------------------------------------------
  void Element::setupStyle()
  {
    BOOST_FOREACH( Style::value_type style, _style )
      setStyle(style.second);
  }

} // namespace canvas
} // namespace simgear
<|endoftext|>


<commit_before>/*
 * Copyright 2021 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/SkTDArray.h"
#include "include/private/chromium/GrSlug.h"
#include "tools/ToolUtils.h"

#if SK_SUPPORT_GPU && defined(SK_EXPERIMENTAL_ADD_ATLAS_PADDING)
class SlugGM : public skiagm::GM {
public:
    SlugGM(const char* txt)
            : fText(txt) {
    }

protected:
    void onOnceBeforeDraw() override {
        fTypeface = ToolUtils::create_portable_typeface("serif", SkFontStyle());
        SkFont font(fTypeface);
        size_t txtLen = strlen(fText);
        int glyphCount = font.countText(fText, txtLen, SkTextEncoding::kUTF8);

        fGlyphs.append(glyphCount);
        font.textToGlyphs(fText, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), glyphCount);
    }

    SkString onShortName() override {
        return SkString("slug");
    }

    SkISize onISize() override {
        return SkISize::Make(1000, 480);
    }

    void onDraw(SkCanvas* canvas) override {
        sk_sp<SkTextBlob> blob(this->makeBlob());
        SkPaint p;
        p.setAntiAlias(true);
        canvas->scale(1.3f, 1.3f);
        sk_sp<GrSlug> slug = GrSlug::ConvertBlob(canvas, *blob, {10, 10}, p);
        if (slug == nullptr) {
            return;
        }
        canvas->translate(0.5, 0.5);
        canvas->translate(30, 30);
        canvas->drawTextBlob(blob, 10, 10, p);
        canvas->translate(370, 0);
        slug->draw(canvas);
        for (float scale = 1.5; scale < 4; scale += 0.5) {
            canvas->translate(-370, 20 * scale);
            canvas->save();
            canvas->scale(scale, scale);
            canvas->rotate(5);
            canvas->drawTextBlob(blob, 10, 10, p);
            canvas->restore();
            canvas->translate(370, 0);
            canvas->save();
            canvas->scale(scale, scale);
            canvas->rotate(5);

            slug->draw(canvas);
            canvas->restore();
        }
    }

private:
    sk_sp<SkTextBlob> makeBlob() {
        SkTextBlobBuilder builder;

        SkFont font;
        font.setSubpixel(true);
        font.setEdging(SkFont::Edging::kAntiAlias);
        font.setTypeface(fTypeface);
        font.setSize(16);

        const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, fGlyphs.count(), 0, 0);
        memcpy(buf.glyphs, fGlyphs.begin(), fGlyphs.count() * sizeof(uint16_t));
        return builder.make();
    }

    SkTDArray<uint16_t> fGlyphs;
    sk_sp<SkTypeface>   fTypeface;
    const char*         fText;
    using INHERITED = skiagm::GM;
};

DEF_GM(return new SlugGM("hamburgefons");)
#endif
<commit_msg>add clipping to slug test<commit_after>/*
 * Copyright 2021 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/SkTDArray.h"
#include "include/private/chromium/GrSlug.h"
#include "tools/ToolUtils.h"

#if SK_SUPPORT_GPU && defined(SK_EXPERIMENTAL_ADD_ATLAS_PADDING)
class SlugGM : public skiagm::GM {
public:
    SlugGM(const char* txt)
            : fText(txt) {
    }

protected:
    void onOnceBeforeDraw() override {
        fTypeface = ToolUtils::create_portable_typeface("serif", SkFontStyle());
        SkFont font(fTypeface);
        size_t txtLen = strlen(fText);
        int glyphCount = font.countText(fText, txtLen, SkTextEncoding::kUTF8);

        fGlyphs.append(glyphCount);
        font.textToGlyphs(fText, txtLen, SkTextEncoding::kUTF8, fGlyphs.begin(), glyphCount);
    }

    SkString onShortName() override {
        return SkString("slug");
    }

    SkISize onISize() override {
        return SkISize::Make(1000, 480);
    }

    void onDraw(SkCanvas* canvas) override {
        sk_sp<SkTextBlob> blob(this->makeBlob());
        SkPaint p;
        p.setAntiAlias(true);
        canvas->clipIRect(SkIRect::MakeSize(this->onISize()));
        canvas->scale(1.3f, 1.3f);
        sk_sp<GrSlug> slug = GrSlug::ConvertBlob(canvas, *blob, {10, 10}, p);
        if (slug == nullptr) {
            return;
        }
        canvas->translate(0.5, 0.5);
        canvas->translate(30, 30);
        canvas->drawTextBlob(blob, 10, 10, p);
        canvas->translate(370, 0);
        slug->draw(canvas);
        for (float scale = 1.5; scale < 4; scale += 0.5) {
            canvas->translate(-370, 20 * scale);
            canvas->save();
            canvas->scale(scale, scale);
            canvas->rotate(5);
            canvas->drawTextBlob(blob, 10, 10, p);
            canvas->restore();
            canvas->translate(370, 0);
            canvas->save();
            canvas->scale(scale, scale);
            canvas->rotate(5);

            slug->draw(canvas);
            canvas->restore();
        }
    }

private:
    sk_sp<SkTextBlob> makeBlob() {
        SkTextBlobBuilder builder;

        SkFont font;
        font.setSubpixel(true);
        font.setEdging(SkFont::Edging::kAntiAlias);
        font.setTypeface(fTypeface);
        font.setSize(16);

        const SkTextBlobBuilder::RunBuffer& buf = builder.allocRun(font, fGlyphs.count(), 0, 0);
        memcpy(buf.glyphs, fGlyphs.begin(), fGlyphs.count() * sizeof(uint16_t));
        return builder.make();
    }

    SkTDArray<uint16_t> fGlyphs;
    sk_sp<SkTypeface>   fTypeface;
    const char*         fText;
    using INHERITED = skiagm::GM;
};

DEF_GM(return new SlugGM("hamburgefons");)
#endif
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: asynclink.hxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: obo $ $Date: 2005-04-13 09:59:13 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef SVTOOLS_ASYNCLINK_HXX
#define  SVTOOLS_ASYNCLINK_HXX

#ifndef INCLUDED_SVTDLLAPI_H
#include "svtools/svtdllapi.h"
#endif

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif
#ifndef _LINK_HXX
#include <tools/link.hxx>
#endif

class Timer;

namespace vos
{
    class OMutex;
}

namespace svtools {

class SVT_DLLPUBLIC AsynchronLink
{
    Link   _aLink;
    ULONG  _nEventId;
    Timer* _pTimer;
    BOOL   _bInCall;
    BOOL*  _pDeleted;
    void*  _pArg;
    vos::OMutex* _pMutex;

    DECL_DLLPRIVATE_STATIC_LINK( AsynchronLink, HandleCall, void* );
    SVT_DLLPRIVATE void Call_Impl( void* pArg );

public:
    AsynchronLink( const Link& rLink ) :
        _aLink( rLink ), _nEventId( 0 ), _pTimer( 0 ), _bInCall( FALSE ),
        _pDeleted( 0 ), _pMutex( 0 ){}
    AsynchronLink() : _nEventId( 0 ), _pTimer( 0 ), _bInCall( FALSE ),
            _pDeleted( 0 ), _pMutex( 0 ){}
    ~AsynchronLink();

    void CreateMutex();
    void operator=( const Link& rLink ) { _aLink = rLink; }
    void Call( void* pObj, BOOL bAllowDoubles = FALSE,
               BOOL bUseTimer = FALSE );
    void ForcePendingCall( );
    void ClearPendingCall( );
    BOOL IsSet() const { return _aLink.IsSet(); }
    Link GetLink() const { return _aLink; }
};

}

#endif
<commit_msg>INTEGRATION: CWS ooo19126 (1.4.140); FILE MERGED 2005/09/05 14:50:28 rt 1.4.140.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: asynclink.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 09:09:13 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef SVTOOLS_ASYNCLINK_HXX
#define  SVTOOLS_ASYNCLINK_HXX

#ifndef INCLUDED_SVTDLLAPI_H
#include "svtools/svtdllapi.h"
#endif

#ifndef _SOLAR_H
#include <tools/solar.h>
#endif
#ifndef _LINK_HXX
#include <tools/link.hxx>
#endif

class Timer;

namespace vos
{
    class OMutex;
}

namespace svtools {

class SVT_DLLPUBLIC AsynchronLink
{
    Link   _aLink;
    ULONG  _nEventId;
    Timer* _pTimer;
    BOOL   _bInCall;
    BOOL*  _pDeleted;
    void*  _pArg;
    vos::OMutex* _pMutex;

    DECL_DLLPRIVATE_STATIC_LINK( AsynchronLink, HandleCall, void* );
    SVT_DLLPRIVATE void Call_Impl( void* pArg );

public:
    AsynchronLink( const Link& rLink ) :
        _aLink( rLink ), _nEventId( 0 ), _pTimer( 0 ), _bInCall( FALSE ),
        _pDeleted( 0 ), _pMutex( 0 ){}
    AsynchronLink() : _nEventId( 0 ), _pTimer( 0 ), _bInCall( FALSE ),
            _pDeleted( 0 ), _pMutex( 0 ){}
    ~AsynchronLink();

    void CreateMutex();
    void operator=( const Link& rLink ) { _aLink = rLink; }
    void Call( void* pObj, BOOL bAllowDoubles = FALSE,
               BOOL bUseTimer = FALSE );
    void ForcePendingCall( );
    void ClearPendingCall( );
    BOOL IsSet() const { return _aLink.IsSet(); }
    Link GetLink() const { return _aLink; }
};

}

#endif
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Initial Developer of the Original Code is
 *       Thorsten Behrens <tbehrens@novell.com>
 * Portions created by the Initial Developer are Copyright (C) 2011 the
 * Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Thorsten Behrens <tbehrens@novell.com>
 *   Caolán McNamara <caolanm@redhat.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */
#include "precompiled_sw.hxx"

#ifdef WNT
#include <prewin.h>
#include <postwin.h>
#endif

#include <cppunit/TestSuite.h>
#include <cppunit/TestFixture.h>
#include <cppunit/TestCase.h>
#include <cppunit/plugin/TestPlugIn.h>
#include <cppunit/extensions/HelperMacros.h>

#include <osl/file.hxx>
#include <osl/process.h>
#include <cppuhelper/compbase1.hxx>
#include <cppuhelper/bootstrap.hxx>
#include <cppuhelper/basemutex.hxx>
#include <comphelper/processfactory.hxx>
#include <vcl/svapp.hxx>
#include <sfx2/app.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/sfxmodelfactory.hxx>
#include <tools/urlobj.hxx>
#include <unotools/tempfile.hxx>
#include <ucbhelper/contentbroker.hxx>

#include "init.hxx"
#include "swtypes.hxx"
#include "doc.hxx"
#include "docsh.hxx"
#include "shellres.hxx"
#include "docufld.hxx"

SO2_DECL_REF(SwDocShell)
SO2_IMPL_REF(SwDocShell)

using namespace ::com::sun::star;

/* Implementation of Swdoc-Test class */

class SwDocTest : public CppUnit::TestFixture
{
public:
    SwDocTest();
    ~SwDocTest();

    virtual void setUp();
    virtual void tearDown();

    void randomTest();
    void testPageDescName();
    void testFileNameFields();

    CPPUNIT_TEST_SUITE(SwDocTest);
    CPPUNIT_TEST(randomTest);
    CPPUNIT_TEST(testPageDescName);
    CPPUNIT_TEST(testFileNameFields);
    CPPUNIT_TEST_SUITE_END();

private:
    uno::Reference<uno::XComponentContext> m_xContext;
    uno::Reference<lang::XMultiComponentFactory> m_xFactory;
    SwDoc *m_pDoc;
    SwDocShellRef m_xDocShRef;
};

void SwDocTest::testPageDescName()
{
    ShellResource aShellResources;

    std::vector<rtl::OUString> aResults;

    //These names must be unique for each different combination, otherwise
    //duplicate page description names may exist, which will causes lookup
    //by name to be incorrect, and so the corresponding export to .odt
    aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::NORMAL_PAGE));
    aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FIRST_PAGE));
    aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FOLLOW_PAGE));

    std::sort(aResults.begin(), aResults.end());
    aResults.erase(std::unique(aResults.begin(), aResults.end()), aResults.end());

    CPPUNIT_ASSERT_MESSAGE("GetPageDescName results must be unique", aResults.size() == 3);
}

//See https://bugs.freedesktop.org/show_bug.cgi?id=32463 for motivation
void SwDocTest::testFileNameFields()
{
    //Here's a file name with some chars in it that will be %% encoded, when expanding
    //SwFileNameFields we want to restore the original readable filename
    utl::TempFile aTempFile(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("demo [name]")));
    aTempFile.EnableKillingFile();

    INetURLObject aTempFileURL(aTempFile.GetURL());
    String sFileURL = aTempFileURL.GetMainURL(INetURLObject::NO_DECODE);
    SfxMedium aDstMed(sFileURL, STREAM_STD_READWRITE, true);

    m_xDocShRef->DoSaveAs(aDstMed);
    m_xDocShRef->DoSaveCompleted(&aDstMed);

    const INetURLObject &rUrlObj = m_xDocShRef->GetMedium()->GetURLObject();

    SwFileNameFieldType aNameField(m_pDoc);

    {
        rtl::OUString sResult(aNameField.Expand(FF_NAME));
        rtl::OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
            true,INetURLObject::DECODE_WITH_CHARSET));
        CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
    }

    {
        rtl::OUString sResult(aNameField.Expand(FF_PATHNAME));
        rtl::OUString sExpected(rUrlObj.GetFull());
        CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
    }

    {
        rtl::OUString sResult(aNameField.Expand(FF_PATH));
        INetURLObject aTemp(rUrlObj);
        aTemp.removeSegment();
        rtl::OUString sExpected(aTemp.PathToFileName());
        CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
    }

    {
        rtl::OUString sResult(aNameField.Expand(FF_NAME_NOEXT));
        rtl::OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
            true,INetURLObject::DECODE_WITH_CHARSET));
        //Chop off .tmp
        sExpected = sExpected.copy(0, sExpected.getLength() - 4);
        CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
    }

    m_xDocShRef->DoInitNew(0);
}

void SwDocTest::randomTest()
{
    CPPUNIT_ASSERT_MESSAGE("SwDoc::IsRedlineOn()", !m_pDoc->IsRedlineOn());
}

SwDocTest::SwDocTest()
{
    m_xContext = cppu::defaultBootstrap_InitialComponentContext();
    m_xFactory = m_xContext->getServiceManager();

    uno::Reference<lang::XMultiServiceFactory> xSM(m_xFactory, uno::UNO_QUERY_THROW);

    //Without this we're crashing because callees are using
    //getProcessServiceFactory.  In general those should be removed in favour
    //of retaining references to the root ServiceFactory as its passed around
    comphelper::setProcessServiceFactory(xSM);

    InitVCL(xSM);

    SwDLL::Init();
}

void SwDocTest::setUp()
{
    m_pDoc = new SwDoc;
    m_xDocShRef = new SwDocShell(m_pDoc, SFX_CREATE_MODE_EMBEDDED);
    m_xDocShRef->DoInitNew(0);
}

SwDocTest::~SwDocTest()
{
}

void SwDocTest::tearDown()
{
    m_xDocShRef.Clear();
    delete m_pDoc;
}

CPPUNIT_TEST_SUITE_REGISTRATION(SwDocTest);

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>no gui warnings please<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Initial Developer of the Original Code is
 *       Thorsten Behrens <tbehrens@novell.com>
 * Portions created by the Initial Developer are Copyright (C) 2011 the
 * Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *   Thorsten Behrens <tbehrens@novell.com>
 *   Caolán McNamara <caolanm@redhat.com>
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */
#include "precompiled_sw.hxx"

#ifdef WNT
#include <prewin.h>
#include <postwin.h>
#endif

#include <cppunit/TestSuite.h>
#include <cppunit/TestFixture.h>
#include <cppunit/TestCase.h>
#include <cppunit/plugin/TestPlugIn.h>
#include <cppunit/extensions/HelperMacros.h>

#include <osl/file.hxx>
#include <osl/process.h>
#include <cppuhelper/compbase1.hxx>
#include <cppuhelper/bootstrap.hxx>
#include <cppuhelper/basemutex.hxx>
#include <comphelper/processfactory.hxx>
#include <vcl/svapp.hxx>
#include <sfx2/app.hxx>
#include <sfx2/docfile.hxx>
#include <sfx2/sfxmodelfactory.hxx>
#include <tools/urlobj.hxx>
#include <unotools/tempfile.hxx>
#include <ucbhelper/contentbroker.hxx>

#include "init.hxx"
#include "swtypes.hxx"
#include "doc.hxx"
#include "docsh.hxx"
#include "shellres.hxx"
#include "docufld.hxx"

SO2_DECL_REF(SwDocShell)
SO2_IMPL_REF(SwDocShell)

using namespace ::com::sun::star;

static USHORT aWndFunc(Window *, USHORT, const String &, const String &)
{
    return ERRCODE_BUTTON_OK;
}

/* Implementation of Swdoc-Test class */

class SwDocTest : public CppUnit::TestFixture
{
public:
    SwDocTest();
    ~SwDocTest();

    virtual void setUp();
    virtual void tearDown();

    void randomTest();
    void testPageDescName();
    void testFileNameFields();

    CPPUNIT_TEST_SUITE(SwDocTest);
    CPPUNIT_TEST(randomTest);
    CPPUNIT_TEST(testPageDescName);
    CPPUNIT_TEST(testFileNameFields);
    CPPUNIT_TEST_SUITE_END();

private:
    uno::Reference<uno::XComponentContext> m_xContext;
    uno::Reference<lang::XMultiComponentFactory> m_xFactory;
    SwDoc *m_pDoc;
    SwDocShellRef m_xDocShRef;
};

void SwDocTest::testPageDescName()
{
    ShellResource aShellResources;

    std::vector<rtl::OUString> aResults;

    //These names must be unique for each different combination, otherwise
    //duplicate page description names may exist, which will causes lookup
    //by name to be incorrect, and so the corresponding export to .odt
    aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::NORMAL_PAGE));
    aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FIRST_PAGE));
    aResults.push_back(aShellResources.GetPageDescName(1, ShellResource::FOLLOW_PAGE));

    std::sort(aResults.begin(), aResults.end());
    aResults.erase(std::unique(aResults.begin(), aResults.end()), aResults.end());

    CPPUNIT_ASSERT_MESSAGE("GetPageDescName results must be unique", aResults.size() == 3);
}

//See https://bugs.freedesktop.org/show_bug.cgi?id=32463 for motivation
void SwDocTest::testFileNameFields()
{
    //Here's a file name with some chars in it that will be %% encoded, when expanding
    //SwFileNameFields we want to restore the original readable filename
    utl::TempFile aTempFile(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("demo [name]")));
    aTempFile.EnableKillingFile();

    INetURLObject aTempFileURL(aTempFile.GetURL());
    String sFileURL = aTempFileURL.GetMainURL(INetURLObject::NO_DECODE);
    SfxMedium aDstMed(sFileURL, STREAM_STD_READWRITE, true);

    m_xDocShRef->DoSaveAs(aDstMed);
    m_xDocShRef->DoSaveCompleted(&aDstMed);

    const INetURLObject &rUrlObj = m_xDocShRef->GetMedium()->GetURLObject();

    SwFileNameFieldType aNameField(m_pDoc);

    {
        rtl::OUString sResult(aNameField.Expand(FF_NAME));
        rtl::OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
            true,INetURLObject::DECODE_WITH_CHARSET));
        CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
    }

    {
        rtl::OUString sResult(aNameField.Expand(FF_PATHNAME));
        rtl::OUString sExpected(rUrlObj.GetFull());
        CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
    }

    {
        rtl::OUString sResult(aNameField.Expand(FF_PATH));
        INetURLObject aTemp(rUrlObj);
        aTemp.removeSegment();
        rtl::OUString sExpected(aTemp.PathToFileName());
        CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
    }

    {
        rtl::OUString sResult(aNameField.Expand(FF_NAME_NOEXT));
        rtl::OUString sExpected(rUrlObj.getName(INetURLObject::LAST_SEGMENT,
            true,INetURLObject::DECODE_WITH_CHARSET));
        //Chop off .tmp
        sExpected = sExpected.copy(0, sExpected.getLength() - 4);
        CPPUNIT_ASSERT_MESSAGE("Expected Readable FileName", sResult == sExpected);
    }

    m_xDocShRef->DoInitNew(0);
}

void SwDocTest::randomTest()
{
    CPPUNIT_ASSERT_MESSAGE("SwDoc::IsRedlineOn()", !m_pDoc->IsRedlineOn());
}

SwDocTest::SwDocTest()
{
    m_xContext = cppu::defaultBootstrap_InitialComponentContext();
    m_xFactory = m_xContext->getServiceManager();

    uno::Reference<lang::XMultiServiceFactory> xSM(m_xFactory, uno::UNO_QUERY_THROW);

    //Without this we're crashing because callees are using
    //getProcessServiceFactory.  In general those should be removed in favour
    //of retaining references to the root ServiceFactory as its passed around
    comphelper::setProcessServiceFactory(xSM);

    InitVCL(xSM);

    SwDLL::Init();

    ErrorHandler::RegisterDisplay(&aWndFunc);
}

void SwDocTest::setUp()
{
    m_pDoc = new SwDoc;
    m_xDocShRef = new SwDocShell(m_pDoc, SFX_CREATE_MODE_EMBEDDED);
    m_xDocShRef->DoInitNew(0);
}

SwDocTest::~SwDocTest()
{
}

void SwDocTest::tearDown()
{
    m_xDocShRef.Clear();
    delete m_pDoc;
}

CPPUNIT_TEST_SUITE_REGISTRATION(SwDocTest);

CPPUNIT_PLUGIN_IMPLEMENT();

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Milian Wolff <mail@milianw.de>
 *
 * This program 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 program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include <QApplication>
#include <QCommandLineParser>

#include <KAboutData>
#include <KLocalizedString>

#include "mainwindow.h"

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    KAboutData aboutData(QStringLiteral("heaptrack_gui"), i18n("Heaptrack GUI"), QStringLiteral("0.1"),
                         i18n("A visualizer for heaptrack data files."), KAboutLicense::LGPL,
                         i18n("Copyright 2015, Milian Wolff <mail@milianw.de>"), QString(), QStringLiteral("mail@milianw.de"));

    aboutData.addAuthor(i18n("Milian Wolff"), i18n("Original author, maintainer"),
                        QStringLiteral("mail@milianw.de"), QStringLiteral("http://milianw.de"));

    aboutData.setOrganizationDomain("kde.org");
    KAboutData::setApplicationData(aboutData);

    app.setApplicationName(aboutData.componentName());
    app.setApplicationDisplayName(aboutData.displayName());
    app.setOrganizationDomain(aboutData.organizationDomain());
    app.setWindowIcon(QIcon::fromTheme(QStringLiteral("office-chart-area")));
    app.setApplicationVersion(aboutData.version());

    QCommandLineParser parser;
    KAboutData::setApplicationData(aboutData);
    parser.addVersionOption();
    parser.addHelpOption();
    aboutData.setupCommandLine(&parser);

    parser.addPositionalArgument(QStringLiteral("files"), i18n( "Files to load" ), i18n("[FILE...]"));

    parser.process(app);
    aboutData.processCommandLine(&parser);

    foreach (const QString &file, parser.positionalArguments()) {
        MainWindow* window = new MainWindow;
        window->loadFile(file);
        window->show();
    }

    return app.exec();
}<commit_msg>Show a window when no files are given.<commit_after>/*
 * Copyright 2015 Milian Wolff <mail@milianw.de>
 *
 * This program 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 program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program; if not, write to the
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */

#include <QApplication>
#include <QCommandLineParser>

#include <KAboutData>
#include <KLocalizedString>

#include "mainwindow.h"

int main(int argc, char** argv)
{
    QApplication app(argc, argv);
    KAboutData aboutData(QStringLiteral("heaptrack_gui"), i18n("Heaptrack GUI"), QStringLiteral("0.1"),
                         i18n("A visualizer for heaptrack data files."), KAboutLicense::LGPL,
                         i18n("Copyright 2015, Milian Wolff <mail@milianw.de>"), QString(), QStringLiteral("mail@milianw.de"));

    aboutData.addAuthor(i18n("Milian Wolff"), i18n("Original author, maintainer"),
                        QStringLiteral("mail@milianw.de"), QStringLiteral("http://milianw.de"));

    aboutData.setOrganizationDomain("kde.org");
    KAboutData::setApplicationData(aboutData);

    app.setApplicationName(aboutData.componentName());
    app.setApplicationDisplayName(aboutData.displayName());
    app.setOrganizationDomain(aboutData.organizationDomain());
    app.setWindowIcon(QIcon::fromTheme(QStringLiteral("office-chart-area")));
    app.setApplicationVersion(aboutData.version());

    QCommandLineParser parser;
    KAboutData::setApplicationData(aboutData);
    parser.addVersionOption();
    parser.addHelpOption();
    aboutData.setupCommandLine(&parser);

    parser.addPositionalArgument(QStringLiteral("files"), i18n( "Files to load" ), i18n("[FILE...]"));

    parser.process(app);
    aboutData.processCommandLine(&parser);

    foreach (const QString &file, parser.positionalArguments()) {
        MainWindow* window = new MainWindow;
        window->loadFile(file);
        window->show();
    }

    if (parser.positionalArguments().isEmpty()) {
        MainWindow* window = new MainWindow;
        window->show();
    }

    return app.exec();
}<|endoftext|>


<commit_before>#include "vanity.hpp"
#define CPU_ONLY

static bool check_prefix(const char * buf){
unsigned short size_str=0;
while(*buf)
{
 if(
 *buf < 48
 ||
 (*buf > 57 && *buf < 65)
 ||
 (*buf > 64 && *buf < 94)
 || *buf > 125
 || size_str > 52
 )return false;
size_str++;
*buf++;
}
return true;
}

static size_t ByteStreamToBase32 (const uint8_t * inBuf, size_t len, char * outBuf, size_t outLen)
{
	size_t ret = 0, pos = 1;
	int bits = 8, tmp = inBuf[0];
	while (ret < outLen && (bits > 0 || pos < len))
	{
		if (bits < 5)
		{
			if (pos < len)
			{
				tmp <<= 8;
	      		tmp |= inBuf[pos] & 0xFF;
				pos++;
	      		bits += 8;
			}
			else // last byte
			{
				tmp <<= (5 - bits);
			  	bits = 5;
			}
		}

		bits -= 5;
		int ind = (tmp >> bits) & 0x1F;
		outBuf[ret] = (ind < 26) ? (ind + 'a') : ((ind - 26) + '2');
		ret++;
	}
	outBuf[ret]='\0';
	return ret;
}

static inline bool NotThat(const char * a, const char *b){
while(*b)
 if(*a++!=*b++) return true;
return false;
}

#ifdef CPU_ONLY
static inline bool thread_find(uint8_t * buf,const char * prefix,int id_thread,unsigned long long throughput){
/*
Thanks to orignal ^-^
For idea and example ^-^
Orignal is sensei of crypto ;)
*/
	std::cout << "Thread " << id_thread << " binded" << std::endl;

	ui4b_t b[391];
	memcpy (b, buf, 391);

	int len = strlen (prefix);

	SHA256_CTX ctx, ctx1;
	SHA256_Init(&ctx);
	SHA256_Update(&ctx, b, MutateByte);

	uint32_t * nonce = (uint32_t *)(b+MutateByte); // in nonce copy of MutateByte of b;
	(*nonce)+=id_thread*throughput;

	uint8_t hash[32];
	char addr[53];

	while(throughput-- and !found){

	memcpy (&ctx1, &ctx, sizeof (SHA256_CTX));
	SHA256_Update(&ctx1, b + MutateByte, 71);
	SHA256_Final(hash, &ctx1);
	ByteStreamToBase32 (hash, 32, addr, len);

	if(	!NotThat(addr,prefix)	){
		ByteStreamToBase32 (hash, 32, addr, 52);
		std::cout << "Address found " << addr << " in " << id_thread << std::endl;
		found=true;
		FoundNonce=*nonce;
		return true;
	}

	(*nonce)++;
	hashescounter++;
	if (found) break;
	}//while
}

#endif

int main (int argc, char * argv[])
{
	if ( argc < 3 )
	{
		std::cout << "Usage: " << argv[0] << " filename generatestring <threads(default of system)> <signature type>" << std::endl;
		return 0;
	}
	if(!check_prefix(argv[2])){
		std::cout << "Not correct prefix" << std::endl;
		return 0;
	}
	i2p::crypto::InitCrypto (false);
	type = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519;
	if ( argc > 3 ){
		unsigned int tmp = atoi(argv[3]);
		if(tmp > 255) {
			std::cout << "Really more than 255 threads?:D Nope, sorry" << std::endl;
			return 0;
		}
		count_cpu=atoi(argv[3]);
	}if ( argc > 4 ) {
		type = NameToSigType(std::string(argv[4]));
	}

///////////////
//For while
if(type != i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519){
	std::cout << "For a while only ED25519-SHA512" << std::endl;
	return 0;
}
///////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			auto keys = i2p::data::PrivateKeys::CreateRandomKeys (type);
			switch(type){
			case i2p::data::SIGNING_KEY_TYPE_DSA_SHA1:
			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA256_2048:
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA384_3072:
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA512_4096:
			case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
			case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST:
			std::cout << "Sorry, i don't can generate adress for this signature type" << std::endl;
			return 0;
			break;
			}
//TODO: for other types.
			switch(type){
			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256:

			break;
			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384:

			break;
			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:

			break;
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA256_2048:

			break;
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA384_3072:

			break;
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA512_4096:

			break;
			case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
			MutateByte=320;
			break;
			case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
			case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST:

			break;
			}

  KeyBuf = new uint8_t[keys.GetFullLen()];
  keys.ToBuffer (KeyBuf, keys.GetFullLen ());

  if(!count_cpu)
   count_cpu = sysconf(_SC_NPROCESSORS_ONLN);

   std::cout << "Start vanity generator in " << count_cpu << " threads" << std::endl;

unsigned short attempts = 0;
while(!found)

{//while
{//stack(for destructors(vector/thread))

  std::vector<std::thread> threads(count_cpu);
  unsigned long long thoughtput = 0x4F4B5A37;

  for ( unsigned int j = count_cpu;j--;){
   threads[j] = std::thread(thread_find,KeyBuf,argv[2],j,thoughtput);
   thoughtput+=1000;
  }//for

  for(unsigned int j = 0; j < count_cpu;j++)
   threads[j].join();

  if(FoundNonce == 0){
	RAND_bytes( KeyBuf+MutateByte , 90 );
	std::cout << "Attempts #" << ++attempts << std::endl;
   }

}//stack
}//while

  memcpy (KeyBuf + MutateByte, &FoundNonce, 4);
  std::cout << "Hashes: " << hashescounter << std::endl;

	std::ofstream f (argv[1], std::ofstream::binary | std::ofstream::out);
	if (f)
	{
		f.write ((char *)KeyBuf, keys.GetFullLen ());
   		delete [] KeyBuf;
	}
	else
		std::cout << "Can't create file " << argv[1] << std::endl;

	i2p::crypto::TerminateCrypto ();

	return 0;
}

<commit_msg>union aligned<commit_after>#include "vanity.hpp"
#define CPU_ONLY

static bool check_prefix(const char * buf){
unsigned short size_str=0;
while(*buf)
{
 if(
 *buf < 48
 ||
 (*buf > 57 && *buf < 65)
 ||
 (*buf > 64 && *buf < 94)
 || *buf > 125
 || size_str > 52
 )return false;
size_str++;
*buf++;
}
return true;
}

static size_t ByteStreamToBase32 (const uint8_t * inBuf, size_t len, char * outBuf, size_t outLen)
{
	size_t ret = 0, pos = 1;
	int bits = 8, tmp = inBuf[0];
	while (ret < outLen && (bits > 0 || pos < len))
	{
		if (bits < 5)
		{
			if (pos < len)
			{
				tmp <<= 8;
	      		tmp |= inBuf[pos] & 0xFF;
				pos++;
	      		bits += 8;
			}
			else // last byte
			{
				tmp <<= (5 - bits);
			  	bits = 5;
			}
		}

		bits -= 5;
		int ind = (tmp >> bits) & 0x1F;
		outBuf[ret] = (ind < 26) ? (ind + 'a') : ((ind - 26) + '2');
		ret++;
	}
	outBuf[ret]='\0';
	return ret;
}

static inline bool NotThat(const char * a, const char *b){
while(*b)
 if(*a++!=*b++) return true;
return false;
}

#ifdef CPU_ONLY
static inline bool thread_find(uint8_t * buf,const char * prefix,int id_thread,unsigned long long throughput){
/*
Thanks to orignal ^-^
For idea and example ^-^
Orignal is sensei of crypto ;)
*/
	std::cout << "Thread " << id_thread << " binded" << std::endl;

	union{
	uint8_t b[391];
	uint32_t ll;
	}local;

	memcpy (local.b, buf, 391);

	int len = strlen (prefix);

	SHA256_CTX ctx, ctx1;
	SHA256_Init(&ctx);
	SHA256_Update(&ctx, local.b, MutateByte);

	uint32_t * nonce = (uint32_t *)(local.b+MutateByte); // in nonce copy of MutateByte of b;
	(*nonce)+=id_thread*throughput;

	uint8_t hash[32];
	char addr[53];

	while(throughput-- and !found){

	memcpy (&ctx1, &ctx, sizeof (SHA256_CTX));
	SHA256_Update(&ctx1, local.b + MutateByte, 71);
	SHA256_Final(hash, &ctx1);
	ByteStreamToBase32 (hash, 32, addr, len);

	if(	!NotThat(addr,prefix)	){
		ByteStreamToBase32 (hash, 32, addr, 52);
		std::cout << "Address found " << addr << " in " << id_thread << std::endl;
		found=true;
		FoundNonce=*nonce;
		return true;
	}

	(*nonce)++;
	hashescounter++;
	if (found) break;
	}//while
}

#endif

int main (int argc, char * argv[])
{
	if ( argc < 3 )
	{
		std::cout << "Usage: " << argv[0] << " filename generatestring <threads(default of system)> <signature type>" << std::endl;
		return 0;
	}
	if(!check_prefix(argv[2])){
		std::cout << "Not correct prefix" << std::endl;
		return 0;
	}
	i2p::crypto::InitCrypto (false);
	type = i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519;
	if ( argc > 3 ){
		unsigned int tmp = atoi(argv[3]);
		if(tmp > 255) {
			std::cout << "Really more than 255 threads?:D Nope, sorry" << std::endl;
			return 0;
		}
		count_cpu=atoi(argv[3]);
	}if ( argc > 4 ) {
		type = NameToSigType(std::string(argv[4]));
	}

///////////////
//For while
if(type != i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519){
	std::cout << "For a while only ED25519-SHA512" << std::endl;
	return 0;
}
///////////////

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
			auto keys = i2p::data::PrivateKeys::CreateRandomKeys (type);
			switch(type){
			case i2p::data::SIGNING_KEY_TYPE_DSA_SHA1:
			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA256_2048:
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA384_3072:
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA512_4096:
			case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512:
			case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST:
			std::cout << "Sorry, i don't can generate adress for this signature type" << std::endl;
			return 0;
			break;
			}
//TODO: for other types.
			switch(type){
			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256:

			break;
			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA384_P384:

			break;
			case i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA512_P521:

			break;
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA256_2048:

			break;
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA384_3072:

			break;
			case i2p::data::SIGNING_KEY_TYPE_RSA_SHA512_4096:

			break;
			case i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519:
			MutateByte=320;
			break;
			case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256:
			case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST:

			break;
			}

  KeyBuf = new uint8_t[keys.GetFullLen()];
  keys.ToBuffer (KeyBuf, keys.GetFullLen ());

  if(!count_cpu)
   count_cpu = sysconf(_SC_NPROCESSORS_ONLN);

   std::cout << "Start vanity generator in " << count_cpu << " threads" << std::endl;

unsigned short attempts = 0;
while(!found)

{//while
{//stack(for destructors(vector/thread))

  std::vector<std::thread> threads(count_cpu);
  unsigned long long thoughtput = 0x4F4B5A37;

  for ( unsigned int j = count_cpu;j--;){
   threads[j] = std::thread(thread_find,KeyBuf,argv[2],j,thoughtput);
   thoughtput+=1000;
  }//for

  for(unsigned int j = 0; j < count_cpu;j++)
   threads[j].join();

  if(FoundNonce == 0){
	RAND_bytes( KeyBuf+MutateByte , 90 );
	std::cout << "Attempts #" << ++attempts << std::endl;
   }

}//stack
}//while

  memcpy (KeyBuf + MutateByte, &FoundNonce, 4);
  std::cout << "Hashes: " << hashescounter << std::endl;

	std::ofstream f (argv[1], std::ofstream::binary | std::ofstream::out);
	if (f)
	{
		f.write ((char *)KeyBuf, keys.GetFullLen ());
   		delete [] KeyBuf;
	}
	else
		std::cout << "Can't create file " << argv[1] << std::endl;

	i2p::crypto::TerminateCrypto ();

	return 0;
}

<|endoftext|>