<commit_before>#include "DBCCFactory.h"
#include "DBCCTextureAtlas.h"
#include "DBCCSlot.h"
#include "DBCCEventDispatcher.h"
#include "DBCCArmature.h"

NAME_SPACE_DRAGON_BONES_BEGIN
DBCCFactory* DBCCFactory::_instance = nullptr;

DBCCFactory* DBCCFactory::getInstance()
{
    if (!_instance)
    {
        _instance = new DBCCFactory();
    }
    return _instance;
}

void DBCCFactory::destroyInstance()
{
    if (_instance)
    {
       CC_SAFE_DELETE(_instance);
    }
}

DBCCFactory::DBCCFactory() {}
DBCCFactory::~DBCCFactory() {}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName);
}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName, const std::string &dragonBonesName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName, dragonBonesName);
}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName, const std::string &skinName, const std::string &animationName,
                                         const std::string &dragonBonesName, const std::string &textureAtlasName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName, skinName, animationName, dragonBonesName, textureAtlasName);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName) const
{
    auto armature = buildArmature(armatureName);
    return DBCCArmatureNode::create(armature);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName, const std::string &dragonBonesName) const
{
    auto armature = buildArmature(armatureName, dragonBonesName);
    return DBCCArmatureNode::create(armature);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName, const std::string &skinName, const std::string &animationName,
    const std::string &dragonBonesName, const std::string &textureAtlasName) const
{
    auto armature = buildArmature(armatureName, skinName, animationName, dragonBonesName, textureAtlasName);
    return DBCCArmatureNode::create(armature);
}

DragonBonesData* DBCCFactory::loadDragonBonesData(const std::string &dragonBonesFilePath, const std::string &name)
{
    DragonBonesData *existDragonBonesData = getDragonBonesData(name);

    if (existDragonBonesData)
    {
        return existDragonBonesData;
    }

    const auto &data = cocos2d::FileUtils::getInstance()->getDataFromFile(dragonBonesFilePath);
    if (data.getSize() == 0)
    {
        return nullptr;
    }

    // armature scale
    float scale = cocos2d::Director::getInstance()->getContentScaleFactor();

    // load skeleton.xml using XML parser.
    dragonBones::XMLDocument doc;
    doc.Parse(reinterpret_cast<char*>(data.getBytes()), data.getSize());
    // paser dragonbones skeleton data.
    dragonBones::XMLDataParser parser;
    DragonBonesData *dragonBonesData = parser.parseDragonBonesData(doc.RootElement(), scale);
    addDragonBonesData(dragonBonesData, name);
    return dragonBonesData;
}

ITextureAtlas* DBCCFactory::loadTextureAtlas(const std::string &textureAtlasFile, const std::string &name)
{
    ITextureAtlas *existTextureAtlas = getTextureAtlas(name);

    if (existTextureAtlas)
    {
        refreshTextureAtlasTexture(name.empty() ? existTextureAtlas->textureAtlasData->name : name);
        return existTextureAtlas;
    }

    const auto &data = cocos2d::FileUtils::getInstance()->getDataFromFile(textureAtlasFile);
    if (data.getSize() == 0)
    {
        return nullptr;
    }

    // textureAtlas scale
    float scale = cocos2d::Director::getInstance()->getContentScaleFactor();

    dragonBones::XMLDocument doc;
    doc.Parse(reinterpret_cast<char*>(data.getBytes()), data.getSize());
    dragonBones::XMLDataParser parser;
    DBCCTextureAtlas *textureAtlas = new DBCCTextureAtlas();
    textureAtlas->textureAtlasData = parser.parseTextureAtlasData(doc.RootElement(), scale);

    int pos = textureAtlasFile.find_last_of("/");

    if (std::string::npos != pos)
    {
        std::string base_path = textureAtlasFile.substr(0, pos + 1);
        textureAtlas->textureAtlasData->imagePath = base_path + textureAtlas->textureAtlasData->imagePath;
    }

    //
    addTextureAtlas(textureAtlas, name);
    refreshTextureAtlasTexture(name.empty() ? textureAtlas->textureAtlasData->name : name);
    return textureAtlas;
}

void DBCCFactory::refreshTextureAtlasTexture(const std::string &name)
{
    for (auto iterator = _textureAtlasMap.begin(); iterator != _textureAtlasMap.end(); ++iterator)
    {
        DBCCTextureAtlas *textureAtlas = static_cast<DBCCTextureAtlas*>(iterator->second);
        const TextureAtlasData *textureAtlasData = textureAtlas->textureAtlasData;

        if (iterator->first == name)
        {
            textureAtlas->reloadTexture();
        }
    }
}

void DBCCFactory::refreshAllTextureAtlasTexture()
{
    for (auto iterator = _textureAtlasMap.begin(); iterator != _textureAtlasMap.end(); ++iterator)
    {
        DBCCTextureAtlas *textureAtlas = static_cast<DBCCTextureAtlas*>(iterator->second);
        const TextureAtlasData *textureAtlasData = textureAtlas->textureAtlasData;
        textureAtlas->reloadTexture();
    }
}

bool DBCCFactory::hasDragonBones(const std::string &skeletonName, const std::string &armatureName, const std::string &animationName)
{
    auto dragonbonesData = getDragonBonesData(skeletonName);

    if (!dragonbonesData) { return false; }

    if (!armatureName.empty())
    {
        auto armatureData = dragonbonesData->getArmatureData(armatureName);

        if (!armatureData) { return false; }

        if (!animationName.empty())
        {
            auto animationData = armatureData->getAnimationData(animationName);
            return animationData != nullptr;
        }
    }

    return true;
}

DBCCArmature* DBCCFactory::generateArmature(const ArmatureData *armatureData) const
{
    Animation *animation = new Animation();
    // sprite
    cocos2d::Node *display = cocos2d::Node::create();
    display->setCascadeColorEnabled(true);
    display->setCascadeOpacityEnabled(true);
    display->retain();
    // eventDispatcher
    DBCCEventDispatcher *eventDispatcher = new DBCCEventDispatcher();
    eventDispatcher->eventDispatcher = new cocos2d::EventDispatcher();
    eventDispatcher->eventDispatcher->setEnabled(true);
    // armature
    return new DBCCArmature((ArmatureData*)(armatureData), animation, eventDispatcher, display);
}

DBCCSlot* DBCCFactory::generateSlot(const SlotData *slotData) const
{
    return new DBCCSlot((SlotData*)(slotData));
}

void* DBCCFactory::generateDisplay(const ITextureAtlas *textureAtlas, const TextureData *textureData, const DisplayData *displayData) const
{
    DBCCTextureAtlas *dbccTextureAtlas = (DBCCTextureAtlas*)(textureAtlas);

    if (!dbccTextureAtlas || !textureData) return nullptr;

    auto texture = dbccTextureAtlas->getTexture();
    assert(texture);

    const float x = textureData->region.x;
    const float y = textureData->region.y;
    const bool rotated = textureData->rotated;
    const float width = rotated ? textureData->region.height : textureData->region.width;
    const float height = rotated ? textureData->region.width : textureData->region.height;
    cocos2d::Rect rect(x, y, width, height);
    cocos2d::Vec2 offset;
    cocos2d::Size originSize(width, height);

    cocos2d::Node *display = nullptr;

    if (textureData->frame)
    {
        float frameX = textureData->frame->x;
        float frameY = textureData->frame->y;
        originSize.width = textureData->frame->width;
        originSize.height = textureData->frame->height;
        // offset = trimed center - origin center
        offset.x = (width - originSize.width) / 2 - frameX;
        offset.y = (height - originSize.height) / 2 - frameY;

        auto spriteFrame = cocos2d::SpriteFrame::createWithTexture(texture, rect,
            textureData->rotated, offset, originSize);
        display = cocos2d::Sprite::createWithSpriteFrame(spriteFrame);
    }
    else
    {
        display = cocos2d::Sprite::createWithTexture(texture, rect, rotated);
    }
    // sprite

    display->setCascadeColorEnabled(true);
    display->setCascadeOpacityEnabled(true);
    display->retain();
    float pivotX = 0.f;
    float pivotY = 0.f;

    if (displayData)
    {
        pivotX = displayData->pivot.x;
        pivotY = displayData->pivot.y;
    }
    display->setAnchorPoint(cocos2d::Vec2(pivotX / originSize.width, 1.f - pivotY / originSize.height));
    display->setContentSize(originSize);
    return display;
}
NAME_SPACE_DRAGON_BONES_END
<commit_msg>fix trim sprite for y<commit_after>#include "DBCCFactory.h"
#include "DBCCTextureAtlas.h"
#include "DBCCSlot.h"
#include "DBCCEventDispatcher.h"
#include "DBCCArmature.h"

NAME_SPACE_DRAGON_BONES_BEGIN
DBCCFactory* DBCCFactory::_instance = nullptr;

DBCCFactory* DBCCFactory::getInstance()
{
    if (!_instance)
    {
        _instance = new DBCCFactory();
    }
    return _instance;
}

void DBCCFactory::destroyInstance()
{
    if (_instance)
    {
       CC_SAFE_DELETE(_instance);
    }
}

DBCCFactory::DBCCFactory() {}
DBCCFactory::~DBCCFactory() {}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName);
}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName, const std::string &dragonBonesName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName, dragonBonesName);
}

DBCCArmature* DBCCFactory::buildArmature(const std::string &armatureName, const std::string &skinName, const std::string &animationName,
                                         const std::string &dragonBonesName, const std::string &textureAtlasName) const
{
    return (DBCCArmature*) BaseFactory::buildArmature(armatureName, skinName, animationName, dragonBonesName, textureAtlasName);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName) const
{
    auto armature = buildArmature(armatureName);
    return DBCCArmatureNode::create(armature);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName, const std::string &dragonBonesName) const
{
    auto armature = buildArmature(armatureName, dragonBonesName);
    return DBCCArmatureNode::create(armature);
}

DBCCArmatureNode* DBCCFactory::buildArmatureNode(const std::string &armatureName, const std::string &skinName, const std::string &animationName,
    const std::string &dragonBonesName, const std::string &textureAtlasName) const
{
    auto armature = buildArmature(armatureName, skinName, animationName, dragonBonesName, textureAtlasName);
    return DBCCArmatureNode::create(armature);
}

DragonBonesData* DBCCFactory::loadDragonBonesData(const std::string &dragonBonesFilePath, const std::string &name)
{
    DragonBonesData *existDragonBonesData = getDragonBonesData(name);

    if (existDragonBonesData)
    {
        return existDragonBonesData;
    }

    const auto &data = cocos2d::FileUtils::getInstance()->getDataFromFile(dragonBonesFilePath);
    if (data.getSize() == 0)
    {
        return nullptr;
    }

    // armature scale
    float scale = cocos2d::Director::getInstance()->getContentScaleFactor();

    // load skeleton.xml using XML parser.
    dragonBones::XMLDocument doc;
    doc.Parse(reinterpret_cast<char*>(data.getBytes()), data.getSize());
    // paser dragonbones skeleton data.
    dragonBones::XMLDataParser parser;
    DragonBonesData *dragonBonesData = parser.parseDragonBonesData(doc.RootElement(), scale);
    addDragonBonesData(dragonBonesData, name);
    return dragonBonesData;
}

ITextureAtlas* DBCCFactory::loadTextureAtlas(const std::string &textureAtlasFile, const std::string &name)
{
    ITextureAtlas *existTextureAtlas = getTextureAtlas(name);

    if (existTextureAtlas)
    {
        refreshTextureAtlasTexture(name.empty() ? existTextureAtlas->textureAtlasData->name : name);
        return existTextureAtlas;
    }

    const auto &data = cocos2d::FileUtils::getInstance()->getDataFromFile(textureAtlasFile);
    if (data.getSize() == 0)
    {
        return nullptr;
    }

    // textureAtlas scale
    float scale = cocos2d::Director::getInstance()->getContentScaleFactor();

    dragonBones::XMLDocument doc;
    doc.Parse(reinterpret_cast<char*>(data.getBytes()), data.getSize());
    dragonBones::XMLDataParser parser;
    DBCCTextureAtlas *textureAtlas = new DBCCTextureAtlas();
    textureAtlas->textureAtlasData = parser.parseTextureAtlasData(doc.RootElement(), scale);

    int pos = textureAtlasFile.find_last_of("/");

    if (std::string::npos != pos)
    {
        std::string base_path = textureAtlasFile.substr(0, pos + 1);
        textureAtlas->textureAtlasData->imagePath = base_path + textureAtlas->textureAtlasData->imagePath;
    }

    //
    addTextureAtlas(textureAtlas, name);
    refreshTextureAtlasTexture(name.empty() ? textureAtlas->textureAtlasData->name : name);
    return textureAtlas;
}

void DBCCFactory::refreshTextureAtlasTexture(const std::string &name)
{
    for (auto iterator = _textureAtlasMap.begin(); iterator != _textureAtlasMap.end(); ++iterator)
    {
        DBCCTextureAtlas *textureAtlas = static_cast<DBCCTextureAtlas*>(iterator->second);
        const TextureAtlasData *textureAtlasData = textureAtlas->textureAtlasData;

        if (iterator->first == name)
        {
            textureAtlas->reloadTexture();
        }
    }
}

void DBCCFactory::refreshAllTextureAtlasTexture()
{
    for (auto iterator = _textureAtlasMap.begin(); iterator != _textureAtlasMap.end(); ++iterator)
    {
        DBCCTextureAtlas *textureAtlas = static_cast<DBCCTextureAtlas*>(iterator->second);
        const TextureAtlasData *textureAtlasData = textureAtlas->textureAtlasData;
        textureAtlas->reloadTexture();
    }
}

bool DBCCFactory::hasDragonBones(const std::string &skeletonName, const std::string &armatureName, const std::string &animationName)
{
    auto dragonbonesData = getDragonBonesData(skeletonName);

    if (!dragonbonesData) { return false; }

    if (!armatureName.empty())
    {
        auto armatureData = dragonbonesData->getArmatureData(armatureName);

        if (!armatureData) { return false; }

        if (!animationName.empty())
        {
            auto animationData = armatureData->getAnimationData(animationName);
            return animationData != nullptr;
        }
    }

    return true;
}

DBCCArmature* DBCCFactory::generateArmature(const ArmatureData *armatureData) const
{
    Animation *animation = new Animation();
    // sprite
    cocos2d::Node *display = cocos2d::Node::create();
    display->setCascadeColorEnabled(true);
    display->setCascadeOpacityEnabled(true);
    display->retain();
    // eventDispatcher
    DBCCEventDispatcher *eventDispatcher = new DBCCEventDispatcher();
    eventDispatcher->eventDispatcher = new cocos2d::EventDispatcher();
    eventDispatcher->eventDispatcher->setEnabled(true);
    // armature
    return new DBCCArmature((ArmatureData*)(armatureData), animation, eventDispatcher, display);
}

DBCCSlot* DBCCFactory::generateSlot(const SlotData *slotData) const
{
    return new DBCCSlot((SlotData*)(slotData));
}

void* DBCCFactory::generateDisplay(const ITextureAtlas *textureAtlas, const TextureData *textureData, const DisplayData *displayData) const
{
    DBCCTextureAtlas *dbccTextureAtlas = (DBCCTextureAtlas*)(textureAtlas);

    if (!dbccTextureAtlas || !textureData) return nullptr;

    auto texture = dbccTextureAtlas->getTexture();
    assert(texture);

    const float x = textureData->region.x;
    const float y = textureData->region.y;
    const bool rotated = textureData->rotated;
    const float width = rotated ? textureData->region.height : textureData->region.width;
    const float height = rotated ? textureData->region.width : textureData->region.height;
    cocos2d::Rect rect(x, y, width, height);
    cocos2d::Vec2 offset;
    cocos2d::Size originSize(width, height);

    cocos2d::Node *display = nullptr;

    if (textureData->frame)
    {
        float frameX = -textureData->frame->x;
        float frameY = -textureData->frame->y;
        originSize.width = textureData->frame->width;
        originSize.height = textureData->frame->height;
        // offset = trimed center - origin center
        // y use cocos2d coordinates
        offset.x = (width - originSize.width) * 0.5 + frameX;
        offset.y = (originSize.height - height)*0.5 - frameY;

        auto spriteFrame = cocos2d::SpriteFrame::createWithTexture(texture, rect,
            textureData->rotated, offset, originSize);
        display = cocos2d::Sprite::createWithSpriteFrame(spriteFrame);
    }
    else
    {
        display = cocos2d::Sprite::createWithTexture(texture, rect, rotated);
    }
    // sprite

    display->setCascadeColorEnabled(true);
    display->setCascadeOpacityEnabled(true);
    display->retain();
    float pivotX = 0.f;
    float pivotY = 0.f;

    if (displayData)
    {
        pivotX = displayData->pivot.x;
        pivotY = displayData->pivot.y;
    }
    display->setAnchorPoint(cocos2d::Vec2(pivotX / originSize.width, 1.f - pivotY / originSize.height));
    display->setContentSize(originSize);
    return display;
}
NAME_SPACE_DRAGON_BONES_END
<|endoftext|>


<commit_before>// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "browser/api/atom_api_protocol.h"

#include "base/memory/weak_ptr.h"
#include "browser/atom_browser_context.h"
#include "browser/atom_url_request_job_factory.h"
#include "content/public/browser/browser_thread.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_error_job.h"
#include "net/url_request/url_request_file_job.h"
#include "net/url_request/url_request_simple_job.h"
#include "vendor/node/src/node.h"
#include "vendor/node/src/node_internals.h"

namespace atom {

namespace api {

namespace {

// The protocol module object.
v8::Persistent<v8::Object> g_protocol_object;

// Registered protocol handlers.
typedef std::map<std::string, v8::Persistent<v8::Function>> HandlersMap;
static HandlersMap g_handlers;

// Emit an event for the protocol module.
void EmitEventInUI(const std::string& event, const std::string& parameter) {
  v8::HandleScope scope;

  v8::Local<v8::Value> argv[] = {
    v8::String::New(event.data(), event.size()),
    v8::String::New(parameter.data(), parameter.size()),
  };
  node::MakeCallback(g_protocol_object, "emit", arraysize(argv), argv);
}

// Convert the URLRequest object to V8 object.
v8::Handle<v8::Object> ConvertURLRequestToV8Object(
    const net::URLRequest* request) {
  v8::Local<v8::Object> obj = v8::Object::New();
  obj->Set(v8::String::New("method"),
           v8::String::New(request->method().c_str()));
  obj->Set(v8::String::New("url"),
           v8::String::New(request->url().spec().c_str()));
  obj->Set(v8::String::New("referrer"),
           v8::String::New(request->referrer().c_str()));
  return obj;
}

// Get the job factory.
AtomURLRequestJobFactory* GetRequestJobFactory() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  return static_cast<AtomURLRequestJobFactory*>(
      const_cast<net::URLRequestJobFactory*>(
          static_cast<content::BrowserContext*>(AtomBrowserContext::Get())->
              GetRequestContext()->GetURLRequestContext()->job_factory()));
}

class URLRequestStringJob : public net::URLRequestSimpleJob {
 public:
  URLRequestStringJob(net::URLRequest* request,
                      net::NetworkDelegate* network_delegate,
                      const std::string& mime_type,
                      const std::string& charset,
                      const std::string& data)
      : net::URLRequestSimpleJob(request, network_delegate),
        mime_type_(mime_type),
        charset_(charset),
        data_(data) {
  }

  // URLRequestSimpleJob:
  virtual int GetData(std::string* mime_type,
                      std::string* charset,
                      std::string* data,
                      const net::CompletionCallback& callback) const OVERRIDE {
    *mime_type = mime_type_;
    *charset = charset_;
    *data = data_;
    return net::OK;
  }

 private:
  std::string mime_type_;
  std::string charset_;
  std::string data_;

  DISALLOW_COPY_AND_ASSIGN(URLRequestStringJob);
};

// Ask JS which type of job it wants, and then delegate corresponding methods.
class AdapterRequestJob : public net::URLRequestJob {
 public:
  AdapterRequestJob(net::URLRequest* request,
                    net::NetworkDelegate* network_delegate)
      : URLRequestJob(request, network_delegate),
        weak_factory_(this) {
  }

 protected:
  // net::URLRequestJob:
  virtual void Start() OVERRIDE {
    DCHECK(!real_job_);
    content::BrowserThread::PostTask(
        content::BrowserThread::UI,
        FROM_HERE,
        base::Bind(&AdapterRequestJob::GetJobTypeInUI,
                   weak_factory_.GetWeakPtr()));
  }

  virtual void Kill() OVERRIDE {
    DCHECK(real_job_);
    real_job_->Kill();
  }

  virtual bool ReadRawData(net::IOBuffer* buf,
                           int buf_size,
                           int *bytes_read) OVERRIDE {
    DCHECK(real_job_);
    // The ReadRawData is a protected method.
    switch (type_) {
      case REQUEST_STRING_JOB:
        return static_cast<URLRequestStringJob*>(real_job_.get())->
            ReadRawData(buf, buf_size, bytes_read);
      case REQUEST_FILE_JOB:
        return static_cast<net::URLRequestFileJob*>(real_job_.get())->
            ReadRawData(buf, buf_size, bytes_read);
      default:
        return net::URLRequestJob::ReadRawData(buf, buf_size, bytes_read);
    }
  }

  virtual bool IsRedirectResponse(GURL* location,
                                  int* http_status_code) OVERRIDE {
    DCHECK(real_job_);
    return real_job_->IsRedirectResponse(location, http_status_code);
  }

  virtual net::Filter* SetupFilter() const OVERRIDE {
    DCHECK(real_job_);
    return real_job_->SetupFilter();
  }

  virtual bool GetMimeType(std::string* mime_type) const OVERRIDE {
    DCHECK(real_job_);
    return real_job_->GetMimeType(mime_type);
  }

  virtual bool GetCharset(std::string* charset) OVERRIDE {
    DCHECK(real_job_);
    return real_job_->GetCharset(charset);
  }

 private:
  enum JOB_TYPE {
    REQUEST_ERROR_JOB,
    REQUEST_STRING_JOB,
    REQUEST_FILE_JOB,
  };

  void GetJobTypeInUI() {
    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

    // Call the JS handler.
    v8::HandleScope scope;
    v8::Handle<v8::Value> argv[] = {
      ConvertURLRequestToV8Object(request()),
    };
    v8::Handle<v8::Value> result = g_handlers[request()->url().scheme()]->Call(
        v8::Context::GetCurrent()->Global(), arraysize(argv), argv);

    // Determine the type of the job we are going to create.
    if (result->IsString()) {
      std::string data = *v8::String::Utf8Value(result);
      content::BrowserThread::PostTask(
          content::BrowserThread::IO,
          FROM_HERE,
          base::Bind(&AdapterRequestJob::CreateStringJobAndStart,
                     weak_factory_.GetWeakPtr(),
                     "text/plain",
                     "UTF-8",
                     data));
      return;
    } else if (result->IsObject()) {
      v8::Handle<v8::Object> obj = result->ToObject();
      std::string name = *v8::String::Utf8Value(obj->GetConstructorName());
      if (name == "RequestStringJob") {
        std::string mime_type = *v8::String::Utf8Value(obj->Get(
            v8::String::New("mimeType")));
        std::string charset = *v8::String::Utf8Value(obj->Get(
            v8::String::New("charset")));
        std::string data = *v8::String::Utf8Value(obj->Get(
            v8::String::New("data")));

        content::BrowserThread::PostTask(
            content::BrowserThread::IO,
            FROM_HERE,
            base::Bind(&AdapterRequestJob::CreateStringJobAndStart,
                       weak_factory_.GetWeakPtr(),
                       mime_type,
                       charset,
                       data));
        return;
      } else if (name == "RequestFileJob") {
        base::FilePath path = base::FilePath::FromUTF8Unsafe(
            *v8::String::Utf8Value(obj->Get(v8::String::New("path"))));

        content::BrowserThread::PostTask(
            content::BrowserThread::IO,
            FROM_HERE,
            base::Bind(&AdapterRequestJob::CreateFileJobAndStart,
                       weak_factory_.GetWeakPtr(),
                       path));
        return;
      }
    }

    // Fallback to the not implemented error.
    content::BrowserThread::PostTask(
        content::BrowserThread::IO,
        FROM_HERE,
        base::Bind(&AdapterRequestJob::CreateErrorJobAndStart,
                   weak_factory_.GetWeakPtr(),
                   net::ERR_NOT_IMPLEMENTED));
  }

  void CreateErrorJobAndStart(int error_code) {
    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

    type_ = REQUEST_ERROR_JOB;
    real_job_ = new net::URLRequestErrorJob(
        request(), network_delegate(), error_code);
    real_job_->Start();
  }

  void CreateStringJobAndStart(const std::string& mime_type,
                               const std::string& charset,
                               const std::string& data) {
    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

    type_ = REQUEST_STRING_JOB;
    real_job_ = new URLRequestStringJob(
        request(), network_delegate(), mime_type, charset, data);
    real_job_->Start();
  }

  void CreateFileJobAndStart(const base::FilePath& path) {
    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

    type_ = REQUEST_FILE_JOB;
    real_job_ = new net::URLRequestFileJob(request(), network_delegate(), path);
    real_job_->Start();
  }

  scoped_refptr<net::URLRequestJob> real_job_;

  // Type of the delegated url request job.
  JOB_TYPE type_;

  base::WeakPtrFactory<AdapterRequestJob> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(AdapterRequestJob);
};

// Always return the same AdapterRequestJob for all requests, because the
// content API needs the ProtocolHandler to return a job immediately, and
// getting the real job from the JS requires asynchronous calls, so we have
// to create an adapter job first.
class AdapterProtocolHandler
    : public net::URLRequestJobFactory::ProtocolHandler {
 public:
  AdapterProtocolHandler() {}
  virtual net::URLRequestJob* MaybeCreateJob(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate) const OVERRIDE {
    return new AdapterRequestJob(request, network_delegate);
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(AdapterProtocolHandler);
};

}  // namespace

// static
v8::Handle<v8::Value> Protocol::RegisterProtocol(const v8::Arguments& args) {
  std::string scheme(*v8::String::Utf8Value(args[0]));
  if (g_handlers.find(scheme) != g_handlers.end() ||
      net::URLRequest::IsHandledProtocol(scheme))
    return node::ThrowError("The scheme is already registered");

  // Store the handler in a map.
  if (!args[1]->IsFunction())
    return node::ThrowError("Handler must be a function");
  g_handlers[scheme] = v8::Persistent<v8::Function>::New(
      node::node_isolate, v8::Handle<v8::Function>::Cast(args[1]));

  content::BrowserThread::PostTask(content::BrowserThread::IO,
                                   FROM_HERE,
                                   base::Bind(&RegisterProtocolInIO, scheme));

  return v8::Undefined();
}

// static
v8::Handle<v8::Value> Protocol::UnregisterProtocol(const v8::Arguments& args) {
  std::string scheme(*v8::String::Utf8Value(args[0]));

  // Erase the handler from map.
  HandlersMap::iterator it(g_handlers.find(scheme));
  if (it == g_handlers.end())
    return node::ThrowError("The scheme has not been registered");
  g_handlers.erase(it);

  content::BrowserThread::PostTask(content::BrowserThread::IO,
                                   FROM_HERE,
                                   base::Bind(&UnregisterProtocolInIO, scheme));

  return v8::Undefined();
}

// static
v8::Handle<v8::Value> Protocol::IsHandledProtocol(const v8::Arguments& args) {
  return v8::Boolean::New(net::URLRequest::IsHandledProtocol(
      *v8::String::Utf8Value(args[0])));
}

// static
v8::Handle<v8::Value> Protocol::InterceptProtocol(const v8::Arguments& args) {
  return v8::Undefined();
}

// static
v8::Handle<v8::Value> Protocol::UninterceptProtocol(const v8::Arguments& args) {
  return v8::Undefined();
}

// static
void Protocol::RegisterProtocolInIO(const std::string& scheme) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  AtomURLRequestJobFactory* job_factory(GetRequestJobFactory());
  job_factory->SetProtocolHandler(scheme, new AdapterProtocolHandler);

  content::BrowserThread::PostTask(content::BrowserThread::UI,
                                   FROM_HERE,
                                   base::Bind(&EmitEventInUI,
                                              "registered",
                                              scheme));
}

// static
void Protocol::UnregisterProtocolInIO(const std::string& scheme) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  AtomURLRequestJobFactory* job_factory(GetRequestJobFactory());
  job_factory->SetProtocolHandler(scheme, NULL);

  content::BrowserThread::PostTask(content::BrowserThread::UI,
                                   FROM_HERE,
                                   base::Bind(&EmitEventInUI,
                                              "unregistered",
                                              scheme));
}

// static
void Protocol::InterceptProtocolInIO(const std::string& scheme) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  AtomURLRequestJobFactory* job_factory(GetRequestJobFactory());
  job_factory->SetProtocolHandler(scheme, new AdapterProtocolHandler);
}

// static
void Protocol::UninterceptProtocolInIO(const std::string& scheme) {
}

// static
void Protocol::Initialize(v8::Handle<v8::Object> target) {
  // Remember the protocol object, used for emitting event later.
  g_protocol_object = v8::Persistent<v8::Object>::New(
      node::node_isolate, target);

  node::SetMethod(target, "registerProtocol", RegisterProtocol);
  node::SetMethod(target, "unregisterProtocol", UnregisterProtocol);
  node::SetMethod(target, "isHandledProtocol", IsHandledProtocol);
}

}  // namespace api

}  // namespace atom

NODE_MODULE(atom_browser_protocol, atom::api::Protocol::Initialize)
<commit_msg>Allow passing a fallback protocol handler for request jobs.<commit_after>// Copyright (c) 2013 GitHub, Inc. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "browser/api/atom_api_protocol.h"

#include "base/memory/weak_ptr.h"
#include "browser/atom_browser_context.h"
#include "browser/atom_url_request_job_factory.h"
#include "content/public/browser/browser_thread.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "net/url_request/url_request_error_job.h"
#include "net/url_request/url_request_file_job.h"
#include "net/url_request/url_request_simple_job.h"
#include "vendor/node/src/node.h"
#include "vendor/node/src/node_internals.h"

namespace atom {

namespace api {

typedef net::URLRequestJobFactory::ProtocolHandler ProtocolHandler;

namespace {

// The protocol module object.
v8::Persistent<v8::Object> g_protocol_object;

// Registered protocol handlers.
typedef std::map<std::string, v8::Persistent<v8::Function>> HandlersMap;
static HandlersMap g_handlers;

// Emit an event for the protocol module.
void EmitEventInUI(const std::string& event, const std::string& parameter) {
  v8::HandleScope scope;

  v8::Local<v8::Value> argv[] = {
    v8::String::New(event.data(), event.size()),
    v8::String::New(parameter.data(), parameter.size()),
  };
  node::MakeCallback(g_protocol_object, "emit", arraysize(argv), argv);
}

// Convert the URLRequest object to V8 object.
v8::Handle<v8::Object> ConvertURLRequestToV8Object(
    const net::URLRequest* request) {
  v8::Local<v8::Object> obj = v8::Object::New();
  obj->Set(v8::String::New("method"),
           v8::String::New(request->method().c_str()));
  obj->Set(v8::String::New("url"),
           v8::String::New(request->url().spec().c_str()));
  obj->Set(v8::String::New("referrer"),
           v8::String::New(request->referrer().c_str()));
  return obj;
}

// Get the job factory.
AtomURLRequestJobFactory* GetRequestJobFactory() {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  return static_cast<AtomURLRequestJobFactory*>(
      const_cast<net::URLRequestJobFactory*>(
          static_cast<content::BrowserContext*>(AtomBrowserContext::Get())->
              GetRequestContext()->GetURLRequestContext()->job_factory()));
}

class URLRequestStringJob : public net::URLRequestSimpleJob {
 public:
  URLRequestStringJob(net::URLRequest* request,
                      net::NetworkDelegate* network_delegate,
                      const std::string& mime_type,
                      const std::string& charset,
                      const std::string& data)
      : net::URLRequestSimpleJob(request, network_delegate),
        mime_type_(mime_type),
        charset_(charset),
        data_(data) {
  }

  // URLRequestSimpleJob:
  virtual int GetData(std::string* mime_type,
                      std::string* charset,
                      std::string* data,
                      const net::CompletionCallback& callback) const OVERRIDE {
    *mime_type = mime_type_;
    *charset = charset_;
    *data = data_;
    return net::OK;
  }

 private:
  std::string mime_type_;
  std::string charset_;
  std::string data_;

  DISALLOW_COPY_AND_ASSIGN(URLRequestStringJob);
};

// Ask JS which type of job it wants, and then delegate corresponding methods.
class AdapterRequestJob : public net::URLRequestJob {
 public:
  AdapterRequestJob(ProtocolHandler* protocol_handler,
                    net::URLRequest* request,
                    net::NetworkDelegate* network_delegate)
      : URLRequestJob(request, network_delegate),
        protocol_handler_(protocol_handler),
        weak_factory_(this) {
  }

 protected:
  // net::URLRequestJob:
  virtual void Start() OVERRIDE {
    DCHECK(!real_job_);
    content::BrowserThread::PostTask(
        content::BrowserThread::UI,
        FROM_HERE,
        base::Bind(&AdapterRequestJob::GetJobTypeInUI,
                   weak_factory_.GetWeakPtr()));
  }

  virtual void Kill() OVERRIDE {
    DCHECK(real_job_);
    real_job_->Kill();
  }

  virtual bool ReadRawData(net::IOBuffer* buf,
                           int buf_size,
                           int *bytes_read) OVERRIDE {
    DCHECK(real_job_);
    // The ReadRawData is a protected method.
    switch (type_) {
      case REQUEST_STRING_JOB:
        return static_cast<URLRequestStringJob*>(real_job_.get())->
            ReadRawData(buf, buf_size, bytes_read);
      case REQUEST_FILE_JOB:
        return static_cast<net::URLRequestFileJob*>(real_job_.get())->
            ReadRawData(buf, buf_size, bytes_read);
      default:
        return net::URLRequestJob::ReadRawData(buf, buf_size, bytes_read);
    }
  }

  virtual bool IsRedirectResponse(GURL* location,
                                  int* http_status_code) OVERRIDE {
    DCHECK(real_job_);
    return real_job_->IsRedirectResponse(location, http_status_code);
  }

  virtual net::Filter* SetupFilter() const OVERRIDE {
    DCHECK(real_job_);
    return real_job_->SetupFilter();
  }

  virtual bool GetMimeType(std::string* mime_type) const OVERRIDE {
    DCHECK(real_job_);
    return real_job_->GetMimeType(mime_type);
  }

  virtual bool GetCharset(std::string* charset) OVERRIDE {
    DCHECK(real_job_);
    return real_job_->GetCharset(charset);
  }

 private:
  enum JOB_TYPE {
    REQUEST_ERROR_JOB,
    REQUEST_STRING_JOB,
    REQUEST_FILE_JOB,
  };

  void GetJobTypeInUI() {
    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));

    // Call the JS handler.
    v8::HandleScope scope;
    v8::Handle<v8::Value> argv[] = {
      ConvertURLRequestToV8Object(request()),
    };
    v8::Handle<v8::Value> result = g_handlers[request()->url().scheme()]->Call(
        v8::Context::GetCurrent()->Global(), arraysize(argv), argv);

    // Determine the type of the job we are going to create.
    if (result->IsString()) {
      std::string data = *v8::String::Utf8Value(result);
      content::BrowserThread::PostTask(
          content::BrowserThread::IO,
          FROM_HERE,
          base::Bind(&AdapterRequestJob::CreateStringJobAndStart,
                     weak_factory_.GetWeakPtr(),
                     "text/plain",
                     "UTF-8",
                     data));
      return;
    } else if (result->IsObject()) {
      v8::Handle<v8::Object> obj = result->ToObject();
      std::string name = *v8::String::Utf8Value(obj->GetConstructorName());
      if (name == "RequestStringJob") {
        std::string mime_type = *v8::String::Utf8Value(obj->Get(
            v8::String::New("mimeType")));
        std::string charset = *v8::String::Utf8Value(obj->Get(
            v8::String::New("charset")));
        std::string data = *v8::String::Utf8Value(obj->Get(
            v8::String::New("data")));

        content::BrowserThread::PostTask(
            content::BrowserThread::IO,
            FROM_HERE,
            base::Bind(&AdapterRequestJob::CreateStringJobAndStart,
                       weak_factory_.GetWeakPtr(),
                       mime_type,
                       charset,
                       data));
        return;
      } else if (name == "RequestFileJob") {
        base::FilePath path = base::FilePath::FromUTF8Unsafe(
            *v8::String::Utf8Value(obj->Get(v8::String::New("path"))));

        content::BrowserThread::PostTask(
            content::BrowserThread::IO,
            FROM_HERE,
            base::Bind(&AdapterRequestJob::CreateFileJobAndStart,
                       weak_factory_.GetWeakPtr(),
                       path));
        return;
      }
    }

    // Try the default protocol handler if we have.
    if (protocol_handler_)
      content::BrowserThread::PostTask(
          content::BrowserThread::IO,
          FROM_HERE,
          base::Bind(&AdapterRequestJob::CreateJobFromProtocolHandlerAndStart,
                     weak_factory_.GetWeakPtr(),
                     protocol_handler_));

    // Fallback to the not implemented error.
    content::BrowserThread::PostTask(
        content::BrowserThread::IO,
        FROM_HERE,
        base::Bind(&AdapterRequestJob::CreateErrorJobAndStart,
                   weak_factory_.GetWeakPtr(),
                   net::ERR_NOT_IMPLEMENTED));
  }

  void CreateErrorJobAndStart(int error_code) {
    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

    type_ = REQUEST_ERROR_JOB;
    real_job_ = new net::URLRequestErrorJob(
        request(), network_delegate(), error_code);
    real_job_->Start();
  }

  void CreateStringJobAndStart(const std::string& mime_type,
                               const std::string& charset,
                               const std::string& data) {
    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

    type_ = REQUEST_STRING_JOB;
    real_job_ = new URLRequestStringJob(
        request(), network_delegate(), mime_type, charset, data);
    real_job_->Start();
  }

  void CreateFileJobAndStart(const base::FilePath& path) {
    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));

    type_ = REQUEST_FILE_JOB;
    real_job_ = new net::URLRequestFileJob(request(), network_delegate(), path);
    real_job_->Start();
  }

  void CreateJobFromProtocolHandlerAndStart(ProtocolHandler* protocol_handler) {
    DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
    DCHECK(protocol_handler_);
    real_job_ = protocol_handler->MaybeCreateJob(request(),
                                                 network_delegate());
    if (!real_job_)
      CreateErrorJobAndStart(net::ERR_NOT_IMPLEMENTED);
    else
      real_job_->Start();
  }

  scoped_refptr<net::URLRequestJob> real_job_;

  // Type of the delegated url request job.
  JOB_TYPE type_;

  // Default protocol handler.
  ProtocolHandler* protocol_handler_;

  base::WeakPtrFactory<AdapterRequestJob> weak_factory_;

  DISALLOW_COPY_AND_ASSIGN(AdapterRequestJob);
};

// Always return the same AdapterRequestJob for all requests, because the
// content API needs the ProtocolHandler to return a job immediately, and
// getting the real job from the JS requires asynchronous calls, so we have
// to create an adapter job first.
// Users can also pass an extra ProtocolHandler as the fallback one when
// registered handler doesn't want to deal with the request.
class AdapterProtocolHandler : public ProtocolHandler {
 public:
  AdapterProtocolHandler(ProtocolHandler* protocol_handler = NULL)
      : protocol_handler_(protocol_handler) {
  }

  virtual net::URLRequestJob* MaybeCreateJob(
      net::URLRequest* request,
      net::NetworkDelegate* network_delegate) const OVERRIDE {
    return new AdapterRequestJob(protocol_handler_.get(),
                                 request,
                                 network_delegate);
  }

 private:
  scoped_ptr<ProtocolHandler> protocol_handler_;

  DISALLOW_COPY_AND_ASSIGN(AdapterProtocolHandler);
};

}  // namespace

// static
v8::Handle<v8::Value> Protocol::RegisterProtocol(const v8::Arguments& args) {
  std::string scheme(*v8::String::Utf8Value(args[0]));
  if (g_handlers.find(scheme) != g_handlers.end() ||
      net::URLRequest::IsHandledProtocol(scheme))
    return node::ThrowError("The scheme is already registered");

  // Store the handler in a map.
  if (!args[1]->IsFunction())
    return node::ThrowError("Handler must be a function");
  g_handlers[scheme] = v8::Persistent<v8::Function>::New(
      node::node_isolate, v8::Handle<v8::Function>::Cast(args[1]));

  content::BrowserThread::PostTask(content::BrowserThread::IO,
                                   FROM_HERE,
                                   base::Bind(&RegisterProtocolInIO, scheme));

  return v8::Undefined();
}

// static
v8::Handle<v8::Value> Protocol::UnregisterProtocol(const v8::Arguments& args) {
  std::string scheme(*v8::String::Utf8Value(args[0]));

  // Erase the handler from map.
  HandlersMap::iterator it(g_handlers.find(scheme));
  if (it == g_handlers.end())
    return node::ThrowError("The scheme has not been registered");
  g_handlers.erase(it);

  content::BrowserThread::PostTask(content::BrowserThread::IO,
                                   FROM_HERE,
                                   base::Bind(&UnregisterProtocolInIO, scheme));

  return v8::Undefined();
}

// static
v8::Handle<v8::Value> Protocol::IsHandledProtocol(const v8::Arguments& args) {
  return v8::Boolean::New(net::URLRequest::IsHandledProtocol(
      *v8::String::Utf8Value(args[0])));
}

// static
v8::Handle<v8::Value> Protocol::InterceptProtocol(const v8::Arguments& args) {
  std::string scheme(*v8::String::Utf8Value(args[0]));
  if (scheme == "https" || scheme == "http")
    return node::ThrowError("Intercepting http protocol is not supported.");

  content::BrowserThread::PostTask(content::BrowserThread::IO,
                                   FROM_HERE,
                                   base::Bind(&UnregisterProtocolInIO, scheme));

  return v8::Undefined();
}

// static
v8::Handle<v8::Value> Protocol::UninterceptProtocol(const v8::Arguments& args) {
  return v8::Undefined();
}

// static
void Protocol::RegisterProtocolInIO(const std::string& scheme) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  AtomURLRequestJobFactory* job_factory(GetRequestJobFactory());
  job_factory->SetProtocolHandler(scheme, new AdapterProtocolHandler);

  content::BrowserThread::PostTask(content::BrowserThread::UI,
                                   FROM_HERE,
                                   base::Bind(&EmitEventInUI,
                                              "registered",
                                              scheme));
}

// static
void Protocol::UnregisterProtocolInIO(const std::string& scheme) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
  AtomURLRequestJobFactory* job_factory(GetRequestJobFactory());
  job_factory->SetProtocolHandler(scheme, NULL);

  content::BrowserThread::PostTask(content::BrowserThread::UI,
                                   FROM_HERE,
                                   base::Bind(&EmitEventInUI,
                                              "unregistered",
                                              scheme));
}

// static
void Protocol::InterceptProtocolInIO(const std::string& scheme) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
}

// static
void Protocol::UninterceptProtocolInIO(const std::string& scheme) {
  DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
}

// static
void Protocol::Initialize(v8::Handle<v8::Object> target) {
  // Remember the protocol object, used for emitting event later.
  g_protocol_object = v8::Persistent<v8::Object>::New(
      node::node_isolate, target);

  node::SetMethod(target, "registerProtocol", RegisterProtocol);
  node::SetMethod(target, "unregisterProtocol", UnregisterProtocol);
  node::SetMethod(target, "isHandledProtocol", IsHandledProtocol);
}

}  // namespace api

}  // namespace atom

NODE_MODULE(atom_browser_protocol, atom::api::Protocol::Initialize)
<|endoftext|>


<commit_before>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <osgProducer/Viewer>

#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/Projection>
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>
#include <osg/CameraNode>
#include <osg/FrontFace>

#include <osgText/Text>

osg::Node* createRearView(osg::Node* subgraph, const osg::Vec4& clearColour)
{
    osg::CameraNode* camera = new osg::CameraNode;

    // set the viewport
    camera->setViewport(420,800,400,200);

    // set the view matrix
    camera->setCullingActive(false);
    camera->setReferenceFrame(osg::Transform::RELATIVE_RF);
    camera->setTransformOrder(osg::CameraNode::POST_MULTIPLE);

    camera->setProjectionMatrix(osg::Matrixd::scale(-1.0f,1.0f,1.0f));
    camera->setViewMatrix(osg::Matrixd::rotate(osg::inDegrees(180.0f),0.0f,1.0f,0.0f));

    // set clear the color and depth buffer
    camera->setClearColor(clearColour);
    camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    // draw subgraph after main camera view.
    camera->setRenderOrder(osg::CameraNode::POST_RENDER);

    // add the subgraph to draw.
    camera->addChild(subgraph);

    // switch of back face culling as we've swapped over the projection matrix making back faces become front faces.
#if 1
    camera->getOrCreateStateSet()->setAttribute(new osg::FrontFace(osg::FrontFace::CLOCKWISE));
#else
    camera->getOrCreateStateSet()->setMode(GL_CULL_FACE, osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);
#endif

    return camera;
}

int main( int argc, char **argv )
{

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates how to do Head Up Displays.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] [filename] ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    // read the scene from the list of file specified commandline args.
    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);

    osg::ref_ptr<osg::Group> group  = new osg::Group;

    // add the HUD subgraph.
    if (scene.valid()) group->addChild(scene.get());
    group->addChild(createRearView(scene.get(), viewer.getClearColor()));

    // set the scene to render
    viewer.setSceneData(group.get());

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<commit_msg>From Marco Jez, moved the rear view camera's viewport to the bottom left of window to accomdate a greater range of display sizes. From Robert Osfield, made the background colour of the intersted camera a scaled down verson of the main background colour to make it more obvious.<commit_after>/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2003 Robert Osfield
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * 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
 * OpenSceneGraph Public License for more details.
*/

#include <osgUtil/Optimizer>
#include <osgDB/ReadFile>
#include <osgProducer/Viewer>

#include <osg/Material>
#include <osg/Geode>
#include <osg/BlendFunc>
#include <osg/Depth>
#include <osg/Projection>
#include <osg/PolygonOffset>
#include <osg/MatrixTransform>
#include <osg/CameraNode>
#include <osg/FrontFace>

#include <osgText/Text>

osg::Node* createRearView(osg::Node* subgraph, const osg::Vec4& clearColour)
{
    osg::CameraNode* camera = new osg::CameraNode;

    // set the viewport
    camera->setViewport(10,10,400,200);

    // set the view matrix
    camera->setCullingActive(false);
    camera->setReferenceFrame(osg::Transform::RELATIVE_RF);
    camera->setTransformOrder(osg::CameraNode::POST_MULTIPLE);

    camera->setProjectionMatrix(osg::Matrixd::scale(-1.0f,1.0f,1.0f));
    camera->setViewMatrix(osg::Matrixd::rotate(osg::inDegrees(180.0f),0.0f,1.0f,0.0f));

    // set clear the color and depth buffer
    camera->setClearColor(clearColour);
    camera->setClearMask(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    // draw subgraph after main camera view.
    camera->setRenderOrder(osg::CameraNode::POST_RENDER);

    // add the subgraph to draw.
    camera->addChild(subgraph);

    // switch of back face culling as we've swapped over the projection matrix making back faces become front faces.
    camera->getOrCreateStateSet()->setAttribute(new osg::FrontFace(osg::FrontFace::CLOCKWISE));

    return camera;
}

int main( int argc, char **argv )
{

    // use an ArgumentParser object to manage the program arguments.
    osg::ArgumentParser arguments(&argc,argv);

    // set up the usage document, in case we need to print out how to use this program.
    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates how to do Head Up Displays.");
    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] [filename] ...");
    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");

    // construct the viewer.
    osgProducer::Viewer viewer(arguments);

    // set up the value with sensible default event handlers.
    viewer.setUpViewer(osgProducer::Viewer::STANDARD_SETTINGS);

    // get details on keyboard and mouse bindings used by the viewer.
    viewer.getUsage(*arguments.getApplicationUsage());

    // if user request help write it out to cout.
    if (arguments.read("-h") || arguments.read("--help"))
    {
        arguments.getApplicationUsage()->write(std::cout);
        return 1;
    }

    // any option left unread are converted into errors to write out later.
    arguments.reportRemainingOptionsAsUnrecognized();

    // report any errors if they have occured when parsing the program aguments.
    if (arguments.errors())
    {
        arguments.writeErrorMessages(std::cout);
        return 1;
    }

    // read the scene from the list of file specified commandline args.
    osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);

    osg::ref_ptr<osg::Group> group  = new osg::Group;

    // add the HUD subgraph.
    if (scene.valid()) group->addChild(scene.get());

    osg::Vec4 colour =  viewer.getClearColor();
    colour.r() *= 0.5f;
    colour.g() *= 0.5f;
    colour.b() *= 0.5f;

    // note tone down the normal back ground colour to make it obvious that there is a seperate camera inserted.
    group->addChild(createRearView(scene.get(), colour));

    // set the scene to render
    viewer.setSceneData(group.get());

    // create the windows and run the threads.
    viewer.realize();

    while( !viewer.done() )
    {
        // wait for all cull and draw threads to complete.
        viewer.sync();

        // update the scene by traversing it with the the update visitor which will
        // call all node update callbacks and animations.
        viewer.update();

        // fire off the cull and draw traversals of the scene.
        viewer.frame();

    }

    // wait for all cull and draw threads to complete before exit.
    viewer.sync();

    return 0;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: sm.hxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: vg $ $Date: 2003-07-22 10:11:43 $
 *
 *  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 _VCL_SM_HXX
#define _VCL_SM_HXX

#include <tools/link.hxx>
#include <salunx.h>
#include <X11/SM/SMlib.h>
#include <osl/conditn.h>

class SessionManagerClient
{
    static SmcConn          aSmcConnection;
    static ByteString       aClientID;
    static oslCondition aSaveCond;
    static bool         bDocSaveDone;

    static void SaveYourselfProc(       SmcConn connection,
                                        SmPointer client_data,
                                        int save_type,
                                        Bool shutdown,
                                        int interact_style,
                                        Bool fast );
    static void DieProc(                SmcConn connection,
                                        SmPointer client_data );
    static void SaveCompleteProc(       SmcConn connection,
                                        SmPointer client_data );
    static void ShutdownCanceledProc(   SmcConn connection,
                                        SmPointer client_data );

    static const ByteString& getPreviousSessionID();

    DECL_STATIC_LINK( SessionManagerClient, ShutDownHdl, void* );
    DECL_STATIC_LINK( SessionManagerClient, SaveYourselfHdl, void* );
public:
    static void open();
    static void close();
    static void checkSaveYourselfCond();

    static bool checkDocumentsSaved();

    static String getExecName();
    static const ByteString&  getSessionID() { return aClientID; }
};

#endif
<commit_msg>INTEGRATION: CWS vcl21 (1.5.224); FILE MERGED 2004/03/18 11:23:21 pl 1.5.224.1: #112891# merge from apoc02<commit_after>/*************************************************************************
 *
 *  $RCSfile: sm.hxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: kz $ $Date: 2004-05-18 10:56:46 $
 *
 *  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 _VCL_SM_HXX
#define _VCL_SM_HXX

#include <tools/link.hxx>
#include <salunx.h>
#include <X11/SM/SMlib.h>
#include <salsession.hxx>

class SessionManagerClient
{
    static SmcConn          aSmcConnection;
    static ByteString       aClientID;
    static bool         bDocSaveDone;

    static void SaveYourselfProc(       SmcConn connection,
                                        SmPointer client_data,
                                        int save_type,
                                        Bool shutdown,
                                        int interact_style,
                                        Bool fast );
    static void DieProc(                SmcConn connection,
                                        SmPointer client_data );
    static void SaveCompleteProc(       SmcConn connection,
                                        SmPointer client_data );
    static void ShutdownCanceledProc(   SmcConn connection,
                                        SmPointer client_data );
    static void InteractProc(           SmcConn connection,
                                        SmPointer clientData );

    static const ByteString& getPreviousSessionID();

    DECL_STATIC_LINK( SessionManagerClient, ShutDownHdl, void* );
    DECL_STATIC_LINK( SessionManagerClient, ShutDownCancelHdl, void* );
    DECL_STATIC_LINK( SessionManagerClient, SaveYourselfHdl, void* );
    DECL_STATIC_LINK( SessionManagerClient, InteractionHdl, void* );
public:
    static void open();
    static void close();

    static bool checkDocumentsSaved();
    static bool queryInteraction();
    static void saveDone();
    static void interactionDone();

    static String getExecName();
    static const ByteString&  getSessionID() { return aClientID; }
};

class SalFrame;

class IceSalSession : public SalSession
{
public:
    IceSalSession();
    virtual ~IceSalSession();

    virtual void queryInteraction();
    virtual void interactionDone();
    virtual void saveDone();
    virtual bool cancelShutdown();

    static void handleOldX11SaveYourself( SalFrame* pFrame );
};

#endif
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkImagePCAShapeModelEstimatorTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
// Insight classes
#include "itkImage.h"
#include "itkVector.h"
#include "vnl/vnl_matrix_fixed.h"
#include "vnl/vnl_math.h"
#include "itkImageRegionIterator.h"
#include "itkLightProcessObject.h"
#include "itkTextOutput.h"

#include "itkImagePCAShapeModelEstimator.h"

//Data definitions
#define   IMGWIDTH            2
#define   IMGHEIGHT           2
#define   NDIMENSION          2
#define   NUMTRAINIMAGES      3
#define   NUMLARGESTPC        2

// class to support progress feeback

class ShowProgressObject
{
public:
  ShowProgressObject(itk::LightProcessObject * o)
    {m_Process = o;}
  void ShowProgress()
    {std::cout << "Progress " << m_Process->GetProgress() << std::endl;}
  itk::LightProcessObject::Pointer m_Process;
};

int itkImagePCAShapeModelEstimatorTest(int, char* [] )
{

  itk::OutputWindow::SetInstance(itk::TextOutput::New().GetPointer());

  //------------------------------------------------------
  //Create 3 simple test images with
  //------------------------------------------------------
  typedef itk::Image<double,NDIMENSION> InputImageType;
  typedef itk::Image<double,NDIMENSION> OutputImageType;
  typedef itk::Image<double,NDIMENSION> MeanImageType;

  typedef InputImageType::PixelType ImagePixelType;

  typedef InputImageType::PixelType InputImagePixelType;

  typedef
    itk::ImageRegionIterator< InputImageType > InputImageIterator;

  typedef
    itk::ImageRegionIterator< OutputImageType > OutputImageIterator;

  InputImageType::Pointer image1 = InputImageType::New();

  InputImageType::Pointer image2 = InputImageType::New();

  InputImageType::Pointer image3 = InputImageType::New();

  InputImageType::SizeType inputImageSize = {{ IMGWIDTH, IMGHEIGHT }};

  InputImageType::IndexType index;
  index.Fill(0);
  InputImageType::RegionType region;

  region.SetSize( inputImageSize );
  region.SetIndex( index );

  //--------------------------------------------------------------------------
  // Set up Image 1 first
  //--------------------------------------------------------------------------

  image1->SetLargestPossibleRegion( region );
  image1->SetBufferedRegion( region );
  image1->Allocate();

  // setup the iterators
  InputImageIterator image1It( image1, image1->GetBufferedRegion() );

  //--------------------------------------------------------------------------
  // Set up Image 2 first
  //--------------------------------------------------------------------------

  image2->SetLargestPossibleRegion( region );
  image2->SetBufferedRegion( region );
  image2->Allocate();

  // setup the iterators
  InputImageIterator image2It( image2, image2->GetBufferedRegion() );

  //--------------------------------------------------------------------------
  // Set up Image 3 first
  //--------------------------------------------------------------------------

  image3->SetLargestPossibleRegion( region );
  image3->SetBufferedRegion( region );
  image3->Allocate();

  // setup the iterators
  InputImageIterator image3It( image3, image3->GetBufferedRegion() );

  //--------------------------------------------------------------------------
  //Manually create and store each vector
  //--------------------------------------------------------------------------
  //Image no. 1
  for( int i = 0; i< 4; i++ )
    {
    image1It.Set( 1 ); ++image1It;
    }
  //Image no. 2
  image2It.Set( 2 ); ++image2It;
  image2It.Set( 0 ); ++image2It;
  image2It.Set( 0 ); ++image2It;
  image2It.Set( 2 ); ++image2It;

  //Image no. 3
  image3It.Set( 0 ); ++image3It;
  image3It.Set( 3 ); ++image3It;
  image3It.Set( 3 ); ++image3It;
  image3It.Set( 0 ); ++image3It;

  //----------------------------------------------------------------------
  // Test code for the Shape model estimator
  //----------------------------------------------------------------------

  //----------------------------------------------------------------------
  //Set the image model estimator
  //----------------------------------------------------------------------
  typedef itk::ImagePCAShapeModelEstimator<InputImageType, OutputImageType>
    ImagePCAShapeModelEstimatorType;

  ImagePCAShapeModelEstimatorType::Pointer
    applyPCAShapeEstimator = ImagePCAShapeModelEstimatorType::New();

  //----------------------------------------------------------------------
  //Set the parameters of the clusterer
  //----------------------------------------------------------------------
  applyPCAShapeEstimator->SetNumberOfTrainingImages( NUMTRAINIMAGES );
  applyPCAShapeEstimator->SetNumberOfPrincipalComponentsRequired( NUMLARGESTPC + 1 );
  applyPCAShapeEstimator->SetNumberOfPrincipalComponentsRequired( NUMLARGESTPC );
  applyPCAShapeEstimator->SetInput(0, image1);
  applyPCAShapeEstimator->SetInput(1, image2);
  applyPCAShapeEstimator->SetInput(2, image3);

  applyPCAShapeEstimator->Update();

  //Test the printself function to increase coverage
  applyPCAShapeEstimator->Print(std::cout);

  //Exercise TypeMacro in superclass
  typedef ImagePCAShapeModelEstimatorType::Superclass GenericEstimatorType;
  std::cout << applyPCAShapeEstimator->GenericEstimatorType::GetNameOfClass() << std::endl;

  //Print out the number of training images and the number of principal
  //components
  std::cout << "The number of training images are: " <<
    applyPCAShapeEstimator->GetNumberOfTrainingImages() << std::endl;

  std::cout << "The number of principal components desired are: " <<
    applyPCAShapeEstimator->GetNumberOfPrincipalComponentsRequired() << std::endl;

  //Print the eigen vectors
  vnl_vector<double> eigenValues =
    applyPCAShapeEstimator->GetEigenValues();
  unsigned int numEigVal =  eigenValues.size();
  std::cout << "Number of returned eign-values: " << numEigVal << std::endl;

  std::cout << "The " <<
    applyPCAShapeEstimator->GetNumberOfPrincipalComponentsRequired() <<
    " largest eigen values are:" << std::endl;

  for(unsigned int i= 0; i< vnl_math_min( numEigVal, (unsigned int)NUMLARGESTPC ); i++ )
    {
    std::cout << eigenValues[ i ] << std::ends;
    }
  std::cout << "" << std::endl;
  std::cout << "" << std::endl;

  //Print the MeanImage
  OutputImageType::Pointer outImage = applyPCAShapeEstimator->GetOutput( 0 );
  OutputImageIterator outImageIt( outImage, outImage->GetBufferedRegion() );
  outImageIt.GoToBegin();

  std::cout << "The mean image is:" << std::endl;
  while(!outImageIt.IsAtEnd() )
    {
    std::cout << (double)(outImageIt.Get()) << ";"  << std::ends;
    ++outImageIt;
    }
  std::cout << "  " << std::endl;

  //Print the largest two eigen vectors
  for (unsigned int j=1; j< NUMLARGESTPC + 1; j++ )
    {
    OutputImageType::Pointer outImage = applyPCAShapeEstimator->GetOutput( j );
    OutputImageIterator outImageIt( outImage, outImage->GetBufferedRegion() );
    outImageIt.GoToBegin();

    std::cout << "" << std::endl;
    std::cout << "The eigen vector number: " << j << " is:" << std::endl;
    while(!outImageIt.IsAtEnd() )
      {
      std::cout << (double) (outImageIt.Get()) << ";"  << std::ends;
      ++outImageIt;
      }
    std::cout << "  " << std::endl;

    }

  //Test for the eigen values for the test case precomputed using Matlab/Splus
  std::cout << "" << std::endl;
  if( (eigenValues[2] < 6 || eigenValues[2] > 6.1) || (eigenValues[1] >0.1) )
    std::cout<< "Test Passed" << std::endl;
  else
    std::cout<< "Test failed" << std::endl;

  return 0;
}
<commit_msg>BUG: std::ends should not be use for std::cout. Use std::endl instead.<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkImagePCAShapeModelEstimatorTest.cxx
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
// Insight classes
#include "itkImage.h"
#include "itkVector.h"
#include "vnl/vnl_matrix_fixed.h"
#include "vnl/vnl_math.h"
#include "itkImageRegionIterator.h"
#include "itkLightProcessObject.h"
#include "itkTextOutput.h"

#include "itkImagePCAShapeModelEstimator.h"

//Data definitions
#define   IMGWIDTH            2
#define   IMGHEIGHT           2
#define   NDIMENSION          2
#define   NUMTRAINIMAGES      3
#define   NUMLARGESTPC        2

// class to support progress feeback

class ShowProgressObject
{
public:
  ShowProgressObject(itk::LightProcessObject * o)
    {m_Process = o;}
  void ShowProgress()
    {std::cout << "Progress " << m_Process->GetProgress() << std::endl;}
  itk::LightProcessObject::Pointer m_Process;
};

int itkImagePCAShapeModelEstimatorTest(int, char* [] )
{

  itk::OutputWindow::SetInstance(itk::TextOutput::New().GetPointer());

  //------------------------------------------------------
  //Create 3 simple test images with
  //------------------------------------------------------
  typedef itk::Image<double,NDIMENSION> InputImageType;
  typedef itk::Image<double,NDIMENSION> OutputImageType;
  typedef itk::Image<double,NDIMENSION> MeanImageType;

  typedef InputImageType::PixelType ImagePixelType;

  typedef InputImageType::PixelType InputImagePixelType;

  typedef
    itk::ImageRegionIterator< InputImageType > InputImageIterator;

  typedef
    itk::ImageRegionIterator< OutputImageType > OutputImageIterator;

  InputImageType::Pointer image1 = InputImageType::New();

  InputImageType::Pointer image2 = InputImageType::New();

  InputImageType::Pointer image3 = InputImageType::New();

  InputImageType::SizeType inputImageSize = {{ IMGWIDTH, IMGHEIGHT }};

  InputImageType::IndexType index;
  index.Fill(0);
  InputImageType::RegionType region;

  region.SetSize( inputImageSize );
  region.SetIndex( index );

  //--------------------------------------------------------------------------
  // Set up Image 1 first
  //--------------------------------------------------------------------------

  image1->SetLargestPossibleRegion( region );
  image1->SetBufferedRegion( region );
  image1->Allocate();

  // setup the iterators
  InputImageIterator image1It( image1, image1->GetBufferedRegion() );

  //--------------------------------------------------------------------------
  // Set up Image 2 first
  //--------------------------------------------------------------------------

  image2->SetLargestPossibleRegion( region );
  image2->SetBufferedRegion( region );
  image2->Allocate();

  // setup the iterators
  InputImageIterator image2It( image2, image2->GetBufferedRegion() );

  //--------------------------------------------------------------------------
  // Set up Image 3 first
  //--------------------------------------------------------------------------

  image3->SetLargestPossibleRegion( region );
  image3->SetBufferedRegion( region );
  image3->Allocate();

  // setup the iterators
  InputImageIterator image3It( image3, image3->GetBufferedRegion() );

  //--------------------------------------------------------------------------
  //Manually create and store each vector
  //--------------------------------------------------------------------------
  //Image no. 1
  for( int i = 0; i< 4; i++ )
    {
    image1It.Set( 1 ); ++image1It;
    }
  //Image no. 2
  image2It.Set( 2 ); ++image2It;
  image2It.Set( 0 ); ++image2It;
  image2It.Set( 0 ); ++image2It;
  image2It.Set( 2 ); ++image2It;

  //Image no. 3
  image3It.Set( 0 ); ++image3It;
  image3It.Set( 3 ); ++image3It;
  image3It.Set( 3 ); ++image3It;
  image3It.Set( 0 ); ++image3It;

  //----------------------------------------------------------------------
  // Test code for the Shape model estimator
  //----------------------------------------------------------------------

  //----------------------------------------------------------------------
  //Set the image model estimator
  //----------------------------------------------------------------------
  typedef itk::ImagePCAShapeModelEstimator<InputImageType, OutputImageType>
    ImagePCAShapeModelEstimatorType;

  ImagePCAShapeModelEstimatorType::Pointer
    applyPCAShapeEstimator = ImagePCAShapeModelEstimatorType::New();

  //----------------------------------------------------------------------
  //Set the parameters of the clusterer
  //----------------------------------------------------------------------
  applyPCAShapeEstimator->SetNumberOfTrainingImages( NUMTRAINIMAGES );
  applyPCAShapeEstimator->SetNumberOfPrincipalComponentsRequired( NUMLARGESTPC + 1 );
  applyPCAShapeEstimator->SetNumberOfPrincipalComponentsRequired( NUMLARGESTPC );
  applyPCAShapeEstimator->SetInput(0, image1);
  applyPCAShapeEstimator->SetInput(1, image2);
  applyPCAShapeEstimator->SetInput(2, image3);

  applyPCAShapeEstimator->Update();

  //Test the printself function to increase coverage
  applyPCAShapeEstimator->Print(std::cout);

  //Exercise TypeMacro in superclass
  typedef ImagePCAShapeModelEstimatorType::Superclass GenericEstimatorType;
  std::cout << applyPCAShapeEstimator->GenericEstimatorType::GetNameOfClass() << std::endl;

  //Print out the number of training images and the number of principal
  //components
  std::cout << "The number of training images are: " <<
    applyPCAShapeEstimator->GetNumberOfTrainingImages() << std::endl;

  std::cout << "The number of principal components desired are: " <<
    applyPCAShapeEstimator->GetNumberOfPrincipalComponentsRequired() << std::endl;

  //Print the eigen vectors
  vnl_vector<double> eigenValues =
    applyPCAShapeEstimator->GetEigenValues();
  unsigned int numEigVal =  eigenValues.size();
  std::cout << "Number of returned eign-values: " << numEigVal << std::endl;

  std::cout << "The " <<
    applyPCAShapeEstimator->GetNumberOfPrincipalComponentsRequired() <<
    " largest eigen values are:" << std::endl;

  for(unsigned int i= 0; i< vnl_math_min( numEigVal, (unsigned int)NUMLARGESTPC ); i++ )
    {
    std::cout << eigenValues[ i ] << std::endl;
    }
  std::cout << "" << std::endl;
  std::cout << "" << std::endl;

  //Print the MeanImage
  OutputImageType::Pointer outImage = applyPCAShapeEstimator->GetOutput( 0 );
  OutputImageIterator outImageIt( outImage, outImage->GetBufferedRegion() );
  outImageIt.GoToBegin();

  std::cout << "The mean image is:" << std::endl;
  while(!outImageIt.IsAtEnd() )
    {
    std::cout << (double)(outImageIt.Get()) << ";"  << std::endl;
    ++outImageIt;
    }
  std::cout << "  " << std::endl;

  //Print the largest two eigen vectors
  for (unsigned int j=1; j< NUMLARGESTPC + 1; j++ )
    {
    OutputImageType::Pointer outImage = applyPCAShapeEstimator->GetOutput( j );
    OutputImageIterator outImageIt( outImage, outImage->GetBufferedRegion() );
    outImageIt.GoToBegin();

    std::cout << "" << std::endl;
    std::cout << "The eigen vector number: " << j << " is:" << std::endl;
    while(!outImageIt.IsAtEnd() )
      {
      std::cout << (double) (outImageIt.Get()) << ";"  << std::endl;
      ++outImageIt;
      }
    std::cout << "  " << std::endl;

    }

  //Test for the eigen values for the test case precomputed using Matlab/Splus
  std::cout << "" << std::endl;
  if( (eigenValues[2] < 6 || eigenValues[2] > 6.1) || (eigenValues[1] >0.1) )
    std::cout<< "Test Passed" << std::endl;
  else
    std::cout<< "Test failed" << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>/*-------------------------------------------------------------------------
 * Vulkan CTS Framework
 * --------------------
 *
 * Copyright (c) 2015 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief SPIR-V assembly to binary.
 *//*--------------------------------------------------------------------*/

#include "vkSpirVAsm.hpp"
#include "vkSpirVProgram.hpp"
#include "deClock.h"

#include <algorithm>

#if defined(DEQP_HAVE_SPIRV_TOOLS)
#	include "spirv-tools/libspirv.h"
#endif

namespace vk
{

using std::string;
using std::vector;

#if defined(DEQP_HAVE_SPIRV_TOOLS)

// Returns the SPIRV-Tools target environment enum for the given dEQP Spirv validator options object.
// Do this here instead of as a method on SpirvValidatorOptions because only this file has access to
// the SPIRV-Tools headers.
static spv_target_env getSpirvToolsEnvForValidatorOptions(SpirvValidatorOptions opts)
{
	const bool allow_1_4 = opts.supports_VK_KHR_spirv_1_4;
	switch (opts.vulkanVersion)
	{
		case VK_MAKE_VERSION(1, 0, 0): return SPV_ENV_VULKAN_1_0;
		case VK_MAKE_VERSION(1, 1, 0): return allow_1_4 ? SPV_ENV_VULKAN_1_1_SPIRV_1_4 : SPV_ENV_VULKAN_1_1;
		//case VK_MAKE_VERSION(1, 2, 0): return SPV_ENV_VULKAN_1_2; // TODO: uncommment when SPV_ENV_VULKAN_1_2 is available
		default:
			break;
	}
	TCU_THROW(InternalError, "Unexpected Vulkan Version version requested");
	return SPV_ENV_VULKAN_1_0;
}

static spv_target_env mapTargetSpvEnvironment(SpirvVersion spirvVersion)
{
	spv_target_env result = SPV_ENV_UNIVERSAL_1_0;

	switch (spirvVersion)
	{
		case SPIRV_VERSION_1_0: result = SPV_ENV_UNIVERSAL_1_0; break;	//!< SPIR-V 1.0
		case SPIRV_VERSION_1_1: result = SPV_ENV_UNIVERSAL_1_1; break;	//!< SPIR-V 1.1
		case SPIRV_VERSION_1_2: result = SPV_ENV_UNIVERSAL_1_2; break;	//!< SPIR-V 1.2
		case SPIRV_VERSION_1_3: result = SPV_ENV_UNIVERSAL_1_3; break;	//!< SPIR-V 1.3
		case SPIRV_VERSION_1_4: result = SPV_ENV_UNIVERSAL_1_4; break;	//!< SPIR-V 1.4
		case SPIRV_VERSION_1_5: result = SPV_ENV_UNIVERSAL_1_5; break;	//!< SPIR-V 1.5
		default:				TCU_THROW(InternalError, "Unknown SPIR-V version");
	}

	return result;
}

bool assembleSpirV (const SpirVAsmSource* program, std::vector<deUint32>* dst, SpirVProgramInfo* buildInfo, SpirvVersion spirvVersion)
{
	const spv_context	context		= spvContextCreate(mapTargetSpvEnvironment(spirvVersion));
	spv_binary			binary		= DE_NULL;
	spv_diagnostic		diagnostic	= DE_NULL;

	if (!context)
		throw std::bad_alloc();

	try
	{
		const std::string&	spvSource			= program->source;
		const deUint64		compileStartTime	= deGetMicroseconds();
		const deUint32		options				= SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS;
		const spv_result_t	compileOk			= spvTextToBinaryWithOptions(context, spvSource.c_str(), spvSource.size(), options, &binary, &diagnostic);

		buildInfo->source			= spvSource;
		buildInfo->infoLog			= diagnostic? diagnostic->error : ""; // \todo [2015-07-13 pyry] Include debug log?
		buildInfo->compileTimeUs	= deGetMicroseconds() - compileStartTime;
		buildInfo->compileOk		= (compileOk == SPV_SUCCESS);

		if (buildInfo->compileOk)
		{
			DE_ASSERT(binary->wordCount > 0);
			dst->resize(binary->wordCount);
			std::copy(&binary->code[0], &binary->code[0] + binary->wordCount, dst->begin());
		}

		spvBinaryDestroy(binary);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);

		return compileOk == SPV_SUCCESS;
	}
	catch (...)
	{
		spvBinaryDestroy(binary);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);

		throw;
	}
}

void disassembleSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* dst, SpirvVersion spirvVersion)
{
	const spv_context	context		= spvContextCreate(mapTargetSpvEnvironment(spirvVersion));
	spv_text			text		= DE_NULL;
	spv_diagnostic		diagnostic	= DE_NULL;

	if (!context)
		throw std::bad_alloc();

	try
	{
		const spv_result_t	result	= spvBinaryToText(context, binary, binarySizeInWords, 0, &text, &diagnostic);

		if (result != SPV_SUCCESS)
			TCU_THROW(InternalError, "Disassembling SPIR-V failed");

		*dst << text->str;

		spvTextDestroy(text);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);
	}
	catch (...)
	{
		spvTextDestroy(text);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);

		throw;
	}
}

bool validateSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* infoLog, const SpirvValidatorOptions &val_options)
{
	const spv_context		context		= spvContextCreate(getSpirvToolsEnvForValidatorOptions(val_options));
	spv_diagnostic			diagnostic	= DE_NULL;
	spv_validator_options	options		= DE_NULL;
	spv_text				disasmText	= DE_NULL;

	if (!context)
		throw std::bad_alloc();

	try
	{
		spv_const_binary_t		cbinary	= { binary, binarySizeInWords };

		options = spvValidatorOptionsCreate();

		if (options == DE_NULL)
			throw std::bad_alloc();

		switch (val_options.blockLayout)
		{
			case SpirvValidatorOptions::kDefaultBlockLayout:
				break;
			case SpirvValidatorOptions::kNoneBlockLayout:
				spvValidatorOptionsSetSkipBlockLayout(options, true);
				break;
			case SpirvValidatorOptions::kRelaxedBlockLayout:
				spvValidatorOptionsSetRelaxBlockLayout(options, true);
				break;
			case SpirvValidatorOptions::kUniformStandardLayout:
				spvValidatorOptionsSetUniformBufferStandardLayout(options, true);
				break;
			case SpirvValidatorOptions::kScalarBlockLayout:
				spvValidatorOptionsSetScalarBlockLayout(options, true);
				break;
		}

		const spv_result_t		valid	= spvValidateWithOptions(context, options, &cbinary, &diagnostic);
		const bool				passed	= (valid == SPV_SUCCESS);

		*infoLog << "Validation " << (passed ? "PASSED: " : "FAILED: ");

		if (diagnostic && diagnostic->error)
		{
			// Print the diagnostic whether validation passes or fails.
			// In theory we could get a warning even in the pass case, but there are no cases
			// like that now.
			*infoLog << diagnostic->error << "\n";

			const deUint32		disasmOptions	= SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES
												| SPV_BINARY_TO_TEXT_OPTION_INDENT;
			const spv_result_t	disasmResult	= spvBinaryToText(context, binary, binarySizeInWords, disasmOptions, &disasmText, DE_NULL);

			if (disasmResult != SPV_SUCCESS)
				*infoLog << "Disassembly failed with code: " << de::toString(disasmResult) << "\n";

			if (disasmText != DE_NULL)
				*infoLog << disasmText->str << "\n";
		}

		spvTextDestroy(disasmText);
		spvValidatorOptionsDestroy(options);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);

		return passed;
	}
	catch (...)
	{
		spvTextDestroy(disasmText);
		spvValidatorOptionsDestroy(options);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);

		throw;
	}
}

#else // defined(DEQP_HAVE_SPIRV_TOOLS)

bool assembleSpirV (const SpirVAsmSource*, std::vector<deUint32>*, SpirVProgramInfo*, SpirvVersion)
{
	TCU_THROW(NotSupportedError, "SPIR-V assembly not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}

void disassembleSpirV (size_t, const deUint32*, std::ostream*, SpirvVersion)
{
	TCU_THROW(NotSupportedError, "SPIR-V disassembling not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}

bool validateSpirV (size_t, const deUint32*, std::ostream*, const SpirvValidatorOptions&)
{
	TCU_THROW(NotSupportedError, "SPIR-V validation not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}

#endif

} // vk
<commit_msg>Uncoment SPV_ENV_VULKAN_1_2 case<commit_after>/*-------------------------------------------------------------------------
 * Vulkan CTS Framework
 * --------------------
 *
 * Copyright (c) 2015 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief SPIR-V assembly to binary.
 *//*--------------------------------------------------------------------*/

#include "vkSpirVAsm.hpp"
#include "vkSpirVProgram.hpp"
#include "deClock.h"

#include <algorithm>

#if defined(DEQP_HAVE_SPIRV_TOOLS)
#	include "spirv-tools/libspirv.h"
#endif

namespace vk
{

using std::string;
using std::vector;

#if defined(DEQP_HAVE_SPIRV_TOOLS)

// Returns the SPIRV-Tools target environment enum for the given dEQP Spirv validator options object.
// Do this here instead of as a method on SpirvValidatorOptions because only this file has access to
// the SPIRV-Tools headers.
static spv_target_env getSpirvToolsEnvForValidatorOptions(SpirvValidatorOptions opts)
{
	const bool allow_1_4 = opts.supports_VK_KHR_spirv_1_4;
	switch (opts.vulkanVersion)
	{
		case VK_MAKE_VERSION(1, 0, 0): return SPV_ENV_VULKAN_1_0;
		case VK_MAKE_VERSION(1, 1, 0): return allow_1_4 ? SPV_ENV_VULKAN_1_1_SPIRV_1_4 : SPV_ENV_VULKAN_1_1;
		case VK_MAKE_VERSION(1, 2, 0): return SPV_ENV_VULKAN_1_2;
		default:
			break;
	}
	TCU_THROW(InternalError, "Unexpected Vulkan Version version requested");
	return SPV_ENV_VULKAN_1_0;
}

static spv_target_env mapTargetSpvEnvironment(SpirvVersion spirvVersion)
{
	spv_target_env result = SPV_ENV_UNIVERSAL_1_0;

	switch (spirvVersion)
	{
		case SPIRV_VERSION_1_0: result = SPV_ENV_UNIVERSAL_1_0; break;	//!< SPIR-V 1.0
		case SPIRV_VERSION_1_1: result = SPV_ENV_UNIVERSAL_1_1; break;	//!< SPIR-V 1.1
		case SPIRV_VERSION_1_2: result = SPV_ENV_UNIVERSAL_1_2; break;	//!< SPIR-V 1.2
		case SPIRV_VERSION_1_3: result = SPV_ENV_UNIVERSAL_1_3; break;	//!< SPIR-V 1.3
		case SPIRV_VERSION_1_4: result = SPV_ENV_UNIVERSAL_1_4; break;	//!< SPIR-V 1.4
		case SPIRV_VERSION_1_5: result = SPV_ENV_UNIVERSAL_1_5; break;	//!< SPIR-V 1.5
		default:				TCU_THROW(InternalError, "Unknown SPIR-V version");
	}

	return result;
}

bool assembleSpirV (const SpirVAsmSource* program, std::vector<deUint32>* dst, SpirVProgramInfo* buildInfo, SpirvVersion spirvVersion)
{
	const spv_context	context		= spvContextCreate(mapTargetSpvEnvironment(spirvVersion));
	spv_binary			binary		= DE_NULL;
	spv_diagnostic		diagnostic	= DE_NULL;

	if (!context)
		throw std::bad_alloc();

	try
	{
		const std::string&	spvSource			= program->source;
		const deUint64		compileStartTime	= deGetMicroseconds();
		const deUint32		options				= SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS;
		const spv_result_t	compileOk			= spvTextToBinaryWithOptions(context, spvSource.c_str(), spvSource.size(), options, &binary, &diagnostic);

		buildInfo->source			= spvSource;
		buildInfo->infoLog			= diagnostic? diagnostic->error : ""; // \todo [2015-07-13 pyry] Include debug log?
		buildInfo->compileTimeUs	= deGetMicroseconds() - compileStartTime;
		buildInfo->compileOk		= (compileOk == SPV_SUCCESS);

		if (buildInfo->compileOk)
		{
			DE_ASSERT(binary->wordCount > 0);
			dst->resize(binary->wordCount);
			std::copy(&binary->code[0], &binary->code[0] + binary->wordCount, dst->begin());
		}

		spvBinaryDestroy(binary);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);

		return compileOk == SPV_SUCCESS;
	}
	catch (...)
	{
		spvBinaryDestroy(binary);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);

		throw;
	}
}

void disassembleSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* dst, SpirvVersion spirvVersion)
{
	const spv_context	context		= spvContextCreate(mapTargetSpvEnvironment(spirvVersion));
	spv_text			text		= DE_NULL;
	spv_diagnostic		diagnostic	= DE_NULL;

	if (!context)
		throw std::bad_alloc();

	try
	{
		const spv_result_t	result	= spvBinaryToText(context, binary, binarySizeInWords, 0, &text, &diagnostic);

		if (result != SPV_SUCCESS)
			TCU_THROW(InternalError, "Disassembling SPIR-V failed");

		*dst << text->str;

		spvTextDestroy(text);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);
	}
	catch (...)
	{
		spvTextDestroy(text);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);

		throw;
	}
}

bool validateSpirV (size_t binarySizeInWords, const deUint32* binary, std::ostream* infoLog, const SpirvValidatorOptions &val_options)
{
	const spv_context		context		= spvContextCreate(getSpirvToolsEnvForValidatorOptions(val_options));
	spv_diagnostic			diagnostic	= DE_NULL;
	spv_validator_options	options		= DE_NULL;
	spv_text				disasmText	= DE_NULL;

	if (!context)
		throw std::bad_alloc();

	try
	{
		spv_const_binary_t		cbinary	= { binary, binarySizeInWords };

		options = spvValidatorOptionsCreate();

		if (options == DE_NULL)
			throw std::bad_alloc();

		switch (val_options.blockLayout)
		{
			case SpirvValidatorOptions::kDefaultBlockLayout:
				break;
			case SpirvValidatorOptions::kNoneBlockLayout:
				spvValidatorOptionsSetSkipBlockLayout(options, true);
				break;
			case SpirvValidatorOptions::kRelaxedBlockLayout:
				spvValidatorOptionsSetRelaxBlockLayout(options, true);
				break;
			case SpirvValidatorOptions::kUniformStandardLayout:
				spvValidatorOptionsSetUniformBufferStandardLayout(options, true);
				break;
			case SpirvValidatorOptions::kScalarBlockLayout:
				spvValidatorOptionsSetScalarBlockLayout(options, true);
				break;
		}

		const spv_result_t		valid	= spvValidateWithOptions(context, options, &cbinary, &diagnostic);
		const bool				passed	= (valid == SPV_SUCCESS);

		*infoLog << "Validation " << (passed ? "PASSED: " : "FAILED: ");

		if (diagnostic && diagnostic->error)
		{
			// Print the diagnostic whether validation passes or fails.
			// In theory we could get a warning even in the pass case, but there are no cases
			// like that now.
			*infoLog << diagnostic->error << "\n";

			const deUint32		disasmOptions	= SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES
												| SPV_BINARY_TO_TEXT_OPTION_INDENT;
			const spv_result_t	disasmResult	= spvBinaryToText(context, binary, binarySizeInWords, disasmOptions, &disasmText, DE_NULL);

			if (disasmResult != SPV_SUCCESS)
				*infoLog << "Disassembly failed with code: " << de::toString(disasmResult) << "\n";

			if (disasmText != DE_NULL)
				*infoLog << disasmText->str << "\n";
		}

		spvTextDestroy(disasmText);
		spvValidatorOptionsDestroy(options);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);

		return passed;
	}
	catch (...)
	{
		spvTextDestroy(disasmText);
		spvValidatorOptionsDestroy(options);
		spvDiagnosticDestroy(diagnostic);
		spvContextDestroy(context);

		throw;
	}
}

#else // defined(DEQP_HAVE_SPIRV_TOOLS)

bool assembleSpirV (const SpirVAsmSource*, std::vector<deUint32>*, SpirVProgramInfo*, SpirvVersion)
{
	TCU_THROW(NotSupportedError, "SPIR-V assembly not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}

void disassembleSpirV (size_t, const deUint32*, std::ostream*, SpirvVersion)
{
	TCU_THROW(NotSupportedError, "SPIR-V disassembling not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}

bool validateSpirV (size_t, const deUint32*, std::ostream*, const SpirvValidatorOptions&)
{
	TCU_THROW(NotSupportedError, "SPIR-V validation not supported (DEQP_HAVE_SPIRV_TOOLS not defined)");
}

#endif

} // vk
<|endoftext|>