<commit_before>#include "base/context/eventlog.h"

#include <string>
#include <utility>

#include "base/context/context.h"

namespace gp = google::protobuf;

namespace vertexai {
namespace context {

EventLog::EventLog() : stream_uuid_(GetRandomUUID()) {}

EventLog::EventLog(boost::uuids::uuid stream_uuid) : stream_uuid_(stream_uuid) {}

std::size_t EventLog::GetClockIndex(const Clock* clock) {
  std::lock_guard<std::mutex> lock{mu_};
  auto res = clock_indicies_.insert(std::make_pair(clock, 0));
  if (res.second) {
    res.first->second = clock_indicies_.size();
  }
  return res.first->second;
}

void Clock::LogActivity(const Context& ctx, const char* verb, gp::Duration start_time, gp::Duration end_time) const {
  if (ctx.is_logging_events()) {
    proto::Event event;
    *event.mutable_parent_id() = ctx.activity_id();
    event.set_verb(verb);
    event.mutable_activity_id()->set_index(ctx.eventlog()->AllocActivityIndex());
    event.mutable_clock_id()->set_index(ctx.eventlog()->GetClockIndex(this));
    *event.mutable_start_time() = start_time;
    *event.mutable_end_time() = end_time;
    *event.mutable_domain_id() = ctx.domain_id();

    ctx.eventlog()->LogEvent(std::move(event));
  }
}

}  // namespace context
}  // namespace vertexai
<commit_msg>Fix eventlog (#146)<commit_after>#include "base/context/eventlog.h"

#include <string>
#include <utility>

#include "base/context/context.h"

namespace gp = google::protobuf;

namespace vertexai {
namespace context {

EventLog::EventLog() : stream_uuid_(GetRandomUUID()), prev_activity_index_(0) {}

EventLog::EventLog(boost::uuids::uuid stream_uuid) : stream_uuid_(stream_uuid), prev_activity_index_(0) {}

std::size_t EventLog::GetClockIndex(const Clock* clock) {
  std::lock_guard<std::mutex> lock{mu_};
  auto res = clock_indicies_.insert(std::make_pair(clock, 0));
  if (res.second) {
    res.first->second = clock_indicies_.size();
  }
  return res.first->second;
}

void Clock::LogActivity(const Context& ctx, const char* verb, gp::Duration start_time, gp::Duration end_time) const {
  if (ctx.is_logging_events()) {
    proto::Event event;
    *event.mutable_parent_id() = ctx.activity_id();
    event.set_verb(verb);
    event.mutable_activity_id()->set_index(ctx.eventlog()->AllocActivityIndex());
    event.mutable_clock_id()->set_index(ctx.eventlog()->GetClockIndex(this));
    *event.mutable_start_time() = start_time;
    *event.mutable_end_time() = end_time;
    *event.mutable_domain_id() = ctx.domain_id();

    ctx.eventlog()->LogEvent(std::move(event));
  }
}

}  // namespace context
}  // namespace vertexai
<|endoftext|>


<commit_before>/*
 * LoggerSCM.cc
 *
 * Copyright (C) 2015 OpenCog Foundation
 *
 * Author: Nil Geisweiller
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/util/Logger.h>
#include <opencog/rule-engine/URELogger.h>
#include <opencog/guile/SchemeModule.h>
#include "SchemePrimitive.h"

using namespace opencog;
namespace opencog {

/**
 * Expose the Logger singleton to Scheme
 */

class LoggerSCM : public ModuleWrap
{
protected:
	virtual void init();

	Logger* do_default_logger();
	Logger* do_ure_logger();
	std::string do_logger_set_level(Logger*, const std::string& level);
	std::string do_logger_get_level(const Logger*);
	std::string do_logger_set_filename(Logger*, const std::string& filename);
	std::string do_logger_get_filename(const Logger*);
	std::string do_logger_set_component(Logger*, const std::string& component);
	std::string do_logger_get_component(const Logger*);
	bool do_logger_set_stdout(Logger*, bool);
	bool do_logger_set_sync(Logger*, bool);
	bool do_logger_set_timestamp(Logger*, bool);
	void do_logger_error(Logger*, const std::string& msg);
	void do_logger_warn(Logger*, const std::string& msg);
	void do_logger_info(Logger*, const std::string& msg);
	void do_logger_debug(Logger*, const std::string& msg);
	void do_logger_fine(Logger*, const std::string& msg);
	bool is_logger(SCM);

public:
	LoggerSCM();
};

/// Get the default logger.
Logger* LoggerSCM::do_default_logger()
{
	return &logger();
}

/// Get the URE logger.
Logger* LoggerSCM::do_ure_logger()
{
	return &ure_logger();
}

/// Set level, return previous level.
std::string LoggerSCM::do_logger_set_level(Logger* lg, const std::string& level)
{
	std::string prev_level;
	prev_level = Logger::get_level_string(lg->get_level());
	lg->set_level(Logger::get_level_from_string(level));
	return prev_level;
}

std::string LoggerSCM::do_logger_get_level(const Logger* lg)
{
	return Logger::get_level_string(lg->get_level());
}

/// Set logfile, return previous file.
std::string LoggerSCM::do_logger_set_filename(Logger* lg, const std::string& filename)
{
	std::string old_file;
	old_file = lg->get_filename();
	lg->set_filename(filename);
	return old_file;
}

std::string LoggerSCM::do_logger_get_filename(const Logger* lg)
{
	return lg->get_filename();
}

/// Set component, return previous component.
std::string LoggerSCM::do_logger_set_component(Logger* lg, const std::string& component)
{
	std::string old_component;
	old_component = lg->get_component();
	lg->set_component(component);
	return old_component;
}

std::string LoggerSCM::do_logger_get_component(const Logger* lg)
{
	return lg->get_component();
}

bool LoggerSCM::do_logger_set_stdout(Logger* lg, bool enable)
{
	// bool previous_setting = lg->get_print_to_stdout_flag();
	bool previous_setting = enable;
	lg->set_print_to_stdout_flag(enable);
	return previous_setting;
}

bool LoggerSCM::do_logger_set_sync(Logger* lg, bool enable)
{
	// bool previous_setting = lg->get_sync_flag();
	bool previous_setting = enable;
	lg->set_sync_flag(enable);
	return previous_setting;
}

bool LoggerSCM::do_logger_set_timestamp(Logger* lg, bool enable)
{
	// bool previous_setting = lg->get_timestamp_flag();
	bool previous_setting = enable;
	lg->set_timestamp_flag(enable);
	return previous_setting;
}

void LoggerSCM::do_logger_error(Logger* lg, const std::string& msg)
{
	lg->error(msg);
}

void LoggerSCM::do_logger_warn(Logger* lg, const std::string& msg)
{
	lg->warn(msg);
}

void LoggerSCM::do_logger_info(Logger* lg, const std::string& msg)
{
	lg->info(msg);
}

void LoggerSCM::do_logger_debug(Logger* lg, const std::string& msg)
{
	lg->debug(msg);
}

void LoggerSCM::do_logger_fine(Logger* lg, const std::string& msg)
{
	lg->fine(msg);
}

bool LoggerSCM::is_logger(SCM s)
{
	return SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, s)
		and SCM_SMOB_FLAGS(s) == SchemeSmob::COG_LOGGER;
}

} /*end of namespace opencog*/

LoggerSCM::LoggerSCM() : ModuleWrap("opencog logger") {}

/// This is called while (opencog logger) is the current module.
/// Thus, all the definitions below happen in that module.
void LoggerSCM::init(void)
{
	define_scheme_primitive("cog-default-logger",
		&LoggerSCM::do_default_logger, this, "logger");
	define_scheme_primitive("cog-ure-logger",
		&LoggerSCM::do_ure_logger, this, "logger");

	define_scheme_primitive("cog-logger-set-level-of-logger!",
		&LoggerSCM::do_logger_set_level, this, "logger");
	define_scheme_primitive("cog-logger-get-level-of-logger",
		&LoggerSCM::do_logger_get_level, this, "logger");

	define_scheme_primitive("cog-logger-set-filename-of-logger!",
		&LoggerSCM::do_logger_set_filename, this, "logger");
	define_scheme_primitive("cog-logger-get-filename-of-logger",
		&LoggerSCM::do_logger_get_filename, this, "logger");

	define_scheme_primitive("cog-logger-set-component-of-logger!",
		&LoggerSCM::do_logger_set_component, this, "logger");
	define_scheme_primitive("cog-logger-get-component-of-logger",
		&LoggerSCM::do_logger_get_component, this, "logger");

	define_scheme_primitive("cog-logger-set-stdout-of-logger!",
		&LoggerSCM::do_logger_set_stdout, this, "logger");
	define_scheme_primitive("cog-logger-set-sync-of-logger!",
		&LoggerSCM::do_logger_set_sync, this, "logger");
	define_scheme_primitive("cog-logger-set-timestamp-of-logger!",
		&LoggerSCM::do_logger_set_timestamp, this, "logger");

	define_scheme_primitive("cog-logger-error-of-logger",
		&LoggerSCM::do_logger_error, this, "logger");
	define_scheme_primitive("cog-logger-warn-of-logger",
		&LoggerSCM::do_logger_warn, this, "logger");
	define_scheme_primitive("cog-logger-info-of-logger",
		&LoggerSCM::do_logger_info, this, "logger");
	define_scheme_primitive("cog-logger-debug-of-logger",
		&LoggerSCM::do_logger_debug, this, "logger");
	define_scheme_primitive("cog-logger-fine-of-logger",
		&LoggerSCM::do_logger_fine, this, "logger");

	define_scheme_primitive("cog-logger?",
		&LoggerSCM::is_logger, this, "logger");
}

extern "C" {
void opencog_logger_init(void);
};

void opencog_logger_init(void)
{
    static LoggerSCM logger_scm;
    logger_scm.module_init();
}
<commit_msg>Add cog-new-logger in LoggerSCM<commit_after>/*
 * LoggerSCM.cc
 *
 * Copyright (C) 2015 OpenCog Foundation
 *
 * Author: Nil Geisweiller
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License v3 as
 * published by the Free Software Foundation and including the exceptions
 * at http://opencog.org/wiki/Licenses
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program; if not, write to:
 * Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include <opencog/util/Logger.h>
#include <opencog/rule-engine/URELogger.h>
#include <opencog/guile/SchemeModule.h>
#include "SchemePrimitive.h"

using namespace opencog;
namespace opencog {

/**
 * Expose the Logger singleton to Scheme
 */

class LoggerSCM : public ModuleWrap
{
protected:
	virtual void init();

	Logger* do_default_logger();
	Logger* do_ure_logger();
	Logger* do_new_logger();
	std::string do_logger_set_level(Logger*, const std::string& level);
	std::string do_logger_get_level(const Logger*);
	std::string do_logger_set_filename(Logger*, const std::string& filename);
	std::string do_logger_get_filename(const Logger*);
	std::string do_logger_set_component(Logger*, const std::string& component);
	std::string do_logger_get_component(const Logger*);
	bool do_logger_set_stdout(Logger*, bool);
	bool do_logger_set_sync(Logger*, bool);
	bool do_logger_set_timestamp(Logger*, bool);
	void do_logger_error(Logger*, const std::string& msg);
	void do_logger_warn(Logger*, const std::string& msg);
	void do_logger_info(Logger*, const std::string& msg);
	void do_logger_debug(Logger*, const std::string& msg);
	void do_logger_fine(Logger*, const std::string& msg);
	bool is_logger(SCM);

public:
	LoggerSCM();
};

/// Get the default logger.
Logger* LoggerSCM::do_default_logger()
{
	return &logger();
}

/// Get the URE logger.
Logger* LoggerSCM::do_ure_logger()
{
	return &ure_logger();
}

/// Create a new logger.
Logger* LoggerSCM::do_new_logger()
{
	Logger* lg = new Logger();
	scm_gc_register_allocation(sizeof(*lg));
	return lg;
}

/// Set level, return previous level.
std::string LoggerSCM::do_logger_set_level(Logger* lg, const std::string& level)
{
	std::string prev_level;
	prev_level = Logger::get_level_string(lg->get_level());
	lg->set_level(Logger::get_level_from_string(level));
	return prev_level;
}

std::string LoggerSCM::do_logger_get_level(const Logger* lg)
{
	return Logger::get_level_string(lg->get_level());
}

/// Set logfile, return previous file.
std::string LoggerSCM::do_logger_set_filename(Logger* lg, const std::string& filename)
{
	std::string old_file;
	old_file = lg->get_filename();
	lg->set_filename(filename);
	return old_file;
}

std::string LoggerSCM::do_logger_get_filename(const Logger* lg)
{
	return lg->get_filename();
}

/// Set component, return previous component.
std::string LoggerSCM::do_logger_set_component(Logger* lg, const std::string& component)
{
	std::string old_component;
	old_component = lg->get_component();
	lg->set_component(component);
	return old_component;
}

std::string LoggerSCM::do_logger_get_component(const Logger* lg)
{
	return lg->get_component();
}

bool LoggerSCM::do_logger_set_stdout(Logger* lg, bool enable)
{
	// bool previous_setting = lg->get_print_to_stdout_flag();
	bool previous_setting = enable;
	lg->set_print_to_stdout_flag(enable);
	return previous_setting;
}

bool LoggerSCM::do_logger_set_sync(Logger* lg, bool enable)
{
	// bool previous_setting = lg->get_sync_flag();
	bool previous_setting = enable;
	lg->set_sync_flag(enable);
	return previous_setting;
}

bool LoggerSCM::do_logger_set_timestamp(Logger* lg, bool enable)
{
	// bool previous_setting = lg->get_timestamp_flag();
	bool previous_setting = enable;
	lg->set_timestamp_flag(enable);
	return previous_setting;
}

void LoggerSCM::do_logger_error(Logger* lg, const std::string& msg)
{
	lg->error(msg);
}

void LoggerSCM::do_logger_warn(Logger* lg, const std::string& msg)
{
	lg->warn(msg);
}

void LoggerSCM::do_logger_info(Logger* lg, const std::string& msg)
{
	lg->info(msg);
}

void LoggerSCM::do_logger_debug(Logger* lg, const std::string& msg)
{
	lg->debug(msg);
}

void LoggerSCM::do_logger_fine(Logger* lg, const std::string& msg)
{
	lg->fine(msg);
}

bool LoggerSCM::is_logger(SCM s)
{
	return SCM_SMOB_PREDICATE(SchemeSmob::cog_misc_tag, s)
		and SCM_SMOB_FLAGS(s) == SchemeSmob::COG_LOGGER;
}

} /*end of namespace opencog*/

LoggerSCM::LoggerSCM() : ModuleWrap("opencog logger") {}

/// This is called while (opencog logger) is the current module.
/// Thus, all the definitions below happen in that module.
void LoggerSCM::init(void)
{
	define_scheme_primitive("cog-default-logger",
		&LoggerSCM::do_default_logger, this, "logger");
	define_scheme_primitive("cog-ure-logger",
		&LoggerSCM::do_ure_logger, this, "logger");
	define_scheme_primitive("cog-new-logger",
		&LoggerSCM::do_new_logger, this, "logger");

	define_scheme_primitive("cog-logger-set-level-of-logger!",
		&LoggerSCM::do_logger_set_level, this, "logger");
	define_scheme_primitive("cog-logger-get-level-of-logger",
		&LoggerSCM::do_logger_get_level, this, "logger");

	define_scheme_primitive("cog-logger-set-filename-of-logger!",
		&LoggerSCM::do_logger_set_filename, this, "logger");
	define_scheme_primitive("cog-logger-get-filename-of-logger",
		&LoggerSCM::do_logger_get_filename, this, "logger");

	define_scheme_primitive("cog-logger-set-component-of-logger!",
		&LoggerSCM::do_logger_set_component, this, "logger");
	define_scheme_primitive("cog-logger-get-component-of-logger",
		&LoggerSCM::do_logger_get_component, this, "logger");

	define_scheme_primitive("cog-logger-set-stdout-of-logger!",
		&LoggerSCM::do_logger_set_stdout, this, "logger");
	define_scheme_primitive("cog-logger-set-sync-of-logger!",
		&LoggerSCM::do_logger_set_sync, this, "logger");
	define_scheme_primitive("cog-logger-set-timestamp-of-logger!",
		&LoggerSCM::do_logger_set_timestamp, this, "logger");

	define_scheme_primitive("cog-logger-error-of-logger",
		&LoggerSCM::do_logger_error, this, "logger");
	define_scheme_primitive("cog-logger-warn-of-logger",
		&LoggerSCM::do_logger_warn, this, "logger");
	define_scheme_primitive("cog-logger-info-of-logger",
		&LoggerSCM::do_logger_info, this, "logger");
	define_scheme_primitive("cog-logger-debug-of-logger",
		&LoggerSCM::do_logger_debug, this, "logger");
	define_scheme_primitive("cog-logger-fine-of-logger",
		&LoggerSCM::do_logger_fine, this, "logger");

	define_scheme_primitive("cog-logger?",
		&LoggerSCM::is_logger, this, "logger");
}

extern "C" {
void opencog_logger_init(void);
};

void opencog_logger_init(void)
{
    static LoggerSCM logger_scm;
    logger_scm.module_init();
}
<|endoftext|>


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

#include "gm.h"
#include "sk_tool_utils.h"
#include "SkColor.h"
#include "SkGradientShader.h"
#include "SkMatrixConvolutionImageFilter.h"
#include "SkPixelRef.h"

namespace skiagm {

class MatrixConvolutionGM : public GM {
public:
    MatrixConvolutionGM(SkColor colorOne, SkColor colorTwo, const char* nameSuffix)
            : fNameSuffix(nameSuffix) {
        this->setBGColor(0x00000000);
        fColors[0] = colorOne;
        fColors[1] = colorTwo;
    }

protected:

    SkString onShortName() override {
        return SkStringPrintf("matrixconvolution%s", fNameSuffix);
    }

    void makeBitmap() {
        // Draw our bitmap in N32, so legacy devices get "premul" values they understand
        SkBitmap n32Bitmap;
        n32Bitmap.allocN32Pixels(80, 80);
        SkCanvas canvas(n32Bitmap);
        canvas.clear(0x00000000);
        SkPaint paint;
        paint.setAntiAlias(true);
        sk_tool_utils::set_portable_typeface(&paint);
        paint.setColor(0xFFFFFFFF);
        paint.setTextSize(SkIntToScalar(180));
        SkPoint pts[2] = { SkPoint::Make(0, 0),
                           SkPoint::Make(0, SkIntToScalar(80)) };
        SkScalar pos[2] = { 0, SkIntToScalar(80) };
        paint.setShader(SkGradientShader::MakeLinear(
            pts, fColors, pos, 2, SkShader::kClamp_TileMode));
        const char* str = "e";
        canvas.drawString(str, SkIntToScalar(-10), SkIntToScalar(80), paint);

        // ... tag the data as sRGB, so color-aware devices do gamut adjustment, etc...
        fBitmap.setInfo(SkImageInfo::MakeS32(80, 80, kPremul_SkAlphaType));
        fBitmap.setPixelRef(sk_ref_sp(n32Bitmap.pixelRef()), 0, 0);
    }

    SkISize onISize() override {
        return SkISize::Make(500, 300);
    }

    void draw(SkCanvas* canvas, int x, int y, const SkIPoint& kernelOffset,
              SkMatrixConvolutionImageFilter::TileMode tileMode, bool convolveAlpha,
              const SkImageFilter::CropRect* cropRect = nullptr) {
        SkScalar kernel[9] = {
            SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
            SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
            SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
        };
        SkISize kernelSize = SkISize::Make(3, 3);
        SkScalar gain = 0.3f, bias = SkIntToScalar(100);
        if (canvas->imageInfo().colorSpace()) {
            // TODO: Gain and bias are poorly specified (in the feConvolveMatrix SVG documentation,
            // there is obviously no mention of gamma or color spaces). Eventually, we need to
            // decide what to do with these (they generally have an extreme brightening effect).
            // For now, I'm modifying this GM to use values tuned to preserve luminance across the
            // range of input values (compared to the legacy math and values).
            //
            // It's impossible to match the results exactly, because legacy math produces a flat
            // response (when looking at sRGB encoded results), while gamma-correct math produces
            // a curve.
            gain = 0.25f;
            bias = 16.5f;
        }
        SkPaint paint;
        paint.setImageFilter(SkMatrixConvolutionImageFilter::Make(kernelSize,
                                                                  kernel,
                                                                  gain,
                                                                  bias,
                                                                  kernelOffset,
                                                                  tileMode,
                                                                  convolveAlpha,
                                                                  nullptr,
                                                                  cropRect));
        canvas->save();
        canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
        const SkRect layerBounds = SkRect::MakeIWH(fBitmap.width(), fBitmap.height());
        canvas->clipRect(layerBounds);
        // This GM is, in part, intended to display the wrapping behavior of the
        // matrix image filter. The only (rational) way to achieve that for repeat mode
        // is to create a tight layer.
        canvas->saveLayer(layerBounds, &paint);
            canvas->drawBitmap(fBitmap, 0, 0, nullptr);
        canvas->restore();
        canvas->restore();
    }

    typedef SkMatrixConvolutionImageFilter MCIF;

    void onOnceBeforeDraw() override {
        this->makeBitmap();
    }

    void onDraw(SkCanvas* canvas) override {
        canvas->clear(SK_ColorBLACK);
        SkIPoint kernelOffset = SkIPoint::Make(1, 0);
        SkImageFilter::CropRect rect(SkRect::Make(fBitmap.bounds()));
        for (int x = 10; x < 310; x += 100) {
            this->draw(canvas, x, 10, kernelOffset, MCIF::kClamp_TileMode, true, &rect);
            this->draw(canvas, x, 110, kernelOffset, MCIF::kClampToBlack_TileMode, true, &rect);
            this->draw(canvas, x, 210, kernelOffset, MCIF::kRepeat_TileMode, true, &rect);
            kernelOffset.fY++;
        }
        kernelOffset.fY = 1;
        SkImageFilter::CropRect smallRect(SkRect::MakeXYWH(10, 5, 60, 60));
        this->draw(canvas, 310, 10, kernelOffset, MCIF::kClamp_TileMode, true, &smallRect);
        this->draw(canvas, 310, 110, kernelOffset, MCIF::kClampToBlack_TileMode, true, &smallRect);
        this->draw(canvas, 310, 210, kernelOffset, MCIF::kRepeat_TileMode, true, &smallRect);

        this->draw(canvas, 410, 10, kernelOffset, MCIF::kClamp_TileMode, false, &rect);
        this->draw(canvas, 410, 110, kernelOffset, MCIF::kClampToBlack_TileMode, false, &rect);
        this->draw(canvas, 410, 210, kernelOffset, MCIF::kRepeat_TileMode, false, &rect);
    }

private:
    SkBitmap fBitmap;
    SkColor fColors[2];
    const char* fNameSuffix;

    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

DEF_GM(return new MatrixConvolutionGM(0xFFFFFFFF, 0x40404040, "");)
DEF_GM(return new MatrixConvolutionGM(0xFFFF0000, 0xFF00FF00, "_color");)

}
<commit_msg>Remove matrixconvolution GM hacks for linear blending<commit_after>/*
 * Copyright 2012 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "gm.h"
#include "sk_tool_utils.h"
#include "SkColor.h"
#include "SkGradientShader.h"
#include "SkMatrixConvolutionImageFilter.h"
#include "SkPixelRef.h"

namespace skiagm {

class MatrixConvolutionGM : public GM {
public:
    MatrixConvolutionGM(SkColor colorOne, SkColor colorTwo, const char* nameSuffix)
            : fNameSuffix(nameSuffix) {
        this->setBGColor(0x00000000);
        fColors[0] = colorOne;
        fColors[1] = colorTwo;
    }

protected:

    SkString onShortName() override {
        return SkStringPrintf("matrixconvolution%s", fNameSuffix);
    }

    void makeBitmap() {
        // Draw our bitmap in N32, so legacy devices get "premul" values they understand
        fBitmap.allocN32Pixels(80, 80);
        SkCanvas canvas(fBitmap);
        canvas.clear(0x00000000);
        SkPaint paint;
        paint.setAntiAlias(true);
        sk_tool_utils::set_portable_typeface(&paint);
        paint.setColor(0xFFFFFFFF);
        paint.setTextSize(SkIntToScalar(180));
        SkPoint pts[2] = { SkPoint::Make(0, 0),
                           SkPoint::Make(0, SkIntToScalar(80)) };
        SkScalar pos[2] = { 0, SkIntToScalar(80) };
        paint.setShader(SkGradientShader::MakeLinear(
            pts, fColors, pos, 2, SkShader::kClamp_TileMode));
        const char* str = "e";
        canvas.drawString(str, SkIntToScalar(-10), SkIntToScalar(80), paint);
    }

    SkISize onISize() override {
        return SkISize::Make(500, 300);
    }

    void draw(SkCanvas* canvas, int x, int y, const SkIPoint& kernelOffset,
              SkMatrixConvolutionImageFilter::TileMode tileMode, bool convolveAlpha,
              const SkImageFilter::CropRect* cropRect = nullptr) {
        SkScalar kernel[9] = {
            SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
            SkIntToScalar( 1), SkIntToScalar(-7), SkIntToScalar( 1),
            SkIntToScalar( 1), SkIntToScalar( 1), SkIntToScalar( 1),
        };
        SkISize kernelSize = SkISize::Make(3, 3);
        SkScalar gain = 0.3f, bias = SkIntToScalar(100);
        SkPaint paint;
        paint.setImageFilter(SkMatrixConvolutionImageFilter::Make(kernelSize,
                                                                  kernel,
                                                                  gain,
                                                                  bias,
                                                                  kernelOffset,
                                                                  tileMode,
                                                                  convolveAlpha,
                                                                  nullptr,
                                                                  cropRect));
        canvas->save();
        canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
        const SkRect layerBounds = SkRect::MakeIWH(fBitmap.width(), fBitmap.height());
        canvas->clipRect(layerBounds);
        // This GM is, in part, intended to display the wrapping behavior of the
        // matrix image filter. The only (rational) way to achieve that for repeat mode
        // is to create a tight layer.
        canvas->saveLayer(layerBounds, &paint);
            canvas->drawBitmap(fBitmap, 0, 0, nullptr);
        canvas->restore();
        canvas->restore();
    }

    typedef SkMatrixConvolutionImageFilter MCIF;

    void onOnceBeforeDraw() override {
        this->makeBitmap();
    }

    void onDraw(SkCanvas* canvas) override {
        canvas->clear(SK_ColorBLACK);
        SkIPoint kernelOffset = SkIPoint::Make(1, 0);
        SkImageFilter::CropRect rect(SkRect::Make(fBitmap.bounds()));
        for (int x = 10; x < 310; x += 100) {
            this->draw(canvas, x, 10, kernelOffset, MCIF::kClamp_TileMode, true, &rect);
            this->draw(canvas, x, 110, kernelOffset, MCIF::kClampToBlack_TileMode, true, &rect);
            this->draw(canvas, x, 210, kernelOffset, MCIF::kRepeat_TileMode, true, &rect);
            kernelOffset.fY++;
        }
        kernelOffset.fY = 1;
        SkImageFilter::CropRect smallRect(SkRect::MakeXYWH(10, 5, 60, 60));
        this->draw(canvas, 310, 10, kernelOffset, MCIF::kClamp_TileMode, true, &smallRect);
        this->draw(canvas, 310, 110, kernelOffset, MCIF::kClampToBlack_TileMode, true, &smallRect);
        this->draw(canvas, 310, 210, kernelOffset, MCIF::kRepeat_TileMode, true, &smallRect);

        this->draw(canvas, 410, 10, kernelOffset, MCIF::kClamp_TileMode, false, &rect);
        this->draw(canvas, 410, 110, kernelOffset, MCIF::kClampToBlack_TileMode, false, &rect);
        this->draw(canvas, 410, 210, kernelOffset, MCIF::kRepeat_TileMode, false, &rect);
    }

private:
    SkBitmap fBitmap;
    SkColor fColors[2];
    const char* fNameSuffix;

    typedef GM INHERITED;
};

//////////////////////////////////////////////////////////////////////////////

DEF_GM(return new MatrixConvolutionGM(0xFFFFFFFF, 0x40404040, "");)
DEF_GM(return new MatrixConvolutionGM(0xFFFF0000, 0xFF00FF00, "_color");)

}
<|endoftext|>


<commit_before>/*
// $Id$
// Fennel is a library of data storage and processing components.
// Copyright (C) 2005-2007 The Eigenbase Project
// Copyright (C) 2005-2007 Disruptive Tech
// Copyright (C) 2005-2007 LucidEra, Inc.
// Portions Copyright (C) 2004-2007 John V. Sichi
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version approved by The Eigenbase Project.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "fennel/common/CommonPreamble.h"
#include "fennel/tuple/StandardTypeDescriptor.h"
#include "fennel/exec/ExecStreamBufAccessor.h"
#include "fennel/exec/ReshapeExecStream.h"

#include <hash_set>

FENNEL_BEGIN_CPPFILE("$Id$");

void ReshapeExecStream::prepare(ReshapeExecStreamParams const &params)
{
    ConduitExecStream::prepare(params);

    TupleDescriptor const &inputDesc = pInAccessor->getTupleDesc();
    TupleAccessor &inputAccessor = pInAccessor->getConsumptionTupleAccessor();
    dynamicParameters.assign(
        params.dynamicParameters.begin(),
        params.dynamicParameters.end());

    compOp = params.compOp;
    if (compOp != COMP_NOOP) {
        initCompareData(params, inputDesc, inputAccessor);
    }

    // Setup the output projection that projects from the input tuple
    outputProjAccessor.bind(inputAccessor, params.outputProj);
    inputOutputDesc.projectFrom(inputDesc, params.outputProj);

    // Setup the output descriptor and data
    outputDesc = pOutAccessor->getTupleDesc();
    outputData.compute(outputDesc);

    // Determine how many of the dynamic parameters need to be written into
    // the output tuple
    uint numOutputDynParams = 0;
    for (uint i = 0; i < dynamicParameters.size(); i++) {
        if (dynamicParameters[i].outputParam) {
            numOutputDynParams++;
        }
    }

    // Setup the output descriptor and data that excludes dynamic parameters
    // in the output tuple
    assert(inputOutputDesc.size() == outputDesc.size() - numOutputDynParams);
    TupleDescriptor partialOutputDesc;
    if (numOutputDynParams == 0) {
        partialOutputDesc = outputDesc;
    } else if (inputOutputDesc.size() > 0) {
        partialOutputDesc.resize(inputOutputDesc.size());
        std::copy(
            outputDesc.begin(),
            outputDesc.end() - numOutputDynParams,
            partialOutputDesc.begin());
    }

    // determine if simple casting is required
    castRequired = (inputOutputDesc != partialOutputDesc);
    if (castRequired) {
        TupleProjection proj;
        if (compOp == COMP_NE) {
            proj = params.inputCompareProj;
        }
        assert(checkCastTypes(proj, inputOutputDesc, partialOutputDesc));
        inputOutputData.compute(inputOutputDesc);
    }
}

void ReshapeExecStream::initCompareData(
    ReshapeExecStreamParams const &params,
    TupleDescriptor const &inputDesc,
    TupleAccessor const &inputAccessor)
{
    // Setup the comparison tuple descriptor
    assert(params.inputCompareProj.size() > 0);
    TupleProjection inputCompareProj = params.inputCompareProj;
    compTupleDesc.projectFrom(inputDesc, inputCompareProj);
    // Adjust the descriptor to allow NULLs in case we're filtering out NULLs
    for (uint i = 0; i < compTupleDesc.size(); i++) {
        compTupleDesc[i].isNullable = true;
    }

    // Setup the projection of the columns for comparison
    inputCompareProjAccessor.bind(inputAccessor, inputCompareProj);
    inputCompareData.compute(compTupleDesc);

    // Setup a descriptor that excludes the dynamic parameters that will
    // be used in comparisons, if there are dynamic parameters.  The dynamic
    // parameters appear at the end of the descriptor.
    TupleDescriptor partialCompTupleDesc;
    numCompDynParams = 0;
    for (uint i = 0; i < dynamicParameters.size(); i++) {
        if (!isMAXU(dynamicParameters[i].compareOffset)) {
            numCompDynParams++;
        }
    }
    if (numCompDynParams > 0) {
        partialCompTupleDesc.resize(compTupleDesc.size() - numCompDynParams);
        std::copy(
            compTupleDesc.begin(),
            compTupleDesc.end() - numCompDynParams,
            partialCompTupleDesc.begin());
    }

    paramCompareData.compute(compTupleDesc);
    if (numCompDynParams == 0) {
        copyCompareTuple(
            compTupleDesc,
            paramCompareData,
            params.pCompTupleBuffer.get());
    } else if (partialCompTupleDesc.size() > 0) {
        TupleData partialCompareData;
        partialCompareData.compute(partialCompTupleDesc);
        copyCompareTuple(
            partialCompTupleDesc,
            partialCompareData,
            params.pCompTupleBuffer.get());

        // Copy the partial tuple data to the tuple data that will
        // be used in the actual comparisons
        std::copy(
            partialCompareData.begin(),
            partialCompareData.end(),
            paramCompareData.begin());
    }

    // Setup a tuple projection to project the last key for use in
    // non-equality comparisons
    lastKey.push_back(paramCompareData.size() - 1);
    lastKeyDesc.projectFrom(compTupleDesc, lastKey);
}

void ReshapeExecStream::copyCompareTuple(
    TupleDescriptor const &tupleDesc,
    TupleData &tupleData,
    PBuffer tupleBuffer)
{
    TupleAccessor tupleAccessor;
    tupleAccessor.compute(tupleDesc);
    tupleAccessor.setCurrentTupleBuf(tupleBuffer);
    uint nBytes = tupleAccessor.getCurrentByteCount();
    compTupleBuffer.reset(new FixedBuffer[nBytes]);
    memcpy(compTupleBuffer.get(), tupleBuffer, nBytes);
    tupleAccessor.setCurrentTupleBuf(compTupleBuffer.get());
    tupleAccessor.unmarshal(tupleData);
}

bool ReshapeExecStream::checkCastTypes(
    const TupleProjection &compareProj,
    const TupleDescriptor &inputTupleDesc,
    const TupleDescriptor &outputTupleDesc)
{
    for (uint i = 0; i < inputTupleDesc.size(); i++) {
        if (!(inputTupleDesc[i] == outputTupleDesc[i])) {
            // only allow not nullable -> nullable, unless nulls are being
            // filtered out from that column
            if (inputTupleDesc[i].isNullable &&
                !outputTupleDesc[i].isNullable)
            {
                assert(nullFilter(compareProj, i));
            } else {
                assert(
                    (inputTupleDesc[i].isNullable ==
                        outputTupleDesc[i].isNullable)
                    || (!inputTupleDesc[i].isNullable
                        && outputTupleDesc[i].isNullable));
            }
            if (inputTupleDesc[i].pTypeDescriptor->getOrdinal() !=
                outputTupleDesc[i].pTypeDescriptor->getOrdinal())
            {
                // if types are different, must be casting from char to
                // varchar
                assert(
                    inputTupleDesc[i].pTypeDescriptor->getOrdinal() ==
                        STANDARD_TYPE_CHAR &&
                    outputTupleDesc[i].pTypeDescriptor->getOrdinal() ==
                        STANDARD_TYPE_VARCHAR);
            }
            if (inputTupleDesc[i].cbStorage != outputTupleDesc[i].cbStorage) {
                // if lengths are different, must be casting from char or
                // varchar to varchar
                assert(
                    (inputTupleDesc[i].pTypeDescriptor->getOrdinal() ==
                        STANDARD_TYPE_VARCHAR ||
                        inputTupleDesc[i].pTypeDescriptor->getOrdinal() ==
                            STANDARD_TYPE_CHAR) &&
                    outputTupleDesc[i].pTypeDescriptor->getOrdinal() ==
                        STANDARD_TYPE_VARCHAR);
            }
        }
    }
    return true;
}

bool ReshapeExecStream::nullFilter(
    const TupleProjection &compareProj, uint colno)
{
    for (uint i = 0; i < compareProj.size(); i++) {
        if (compareProj[i] == colno) {
            if (!paramCompareData[i].pData) {
                return true;
            } else {
                break;
            }
        }
    }
    return false;
}

void ReshapeExecStream::open(bool restart)
{
    ConduitExecStream::open(restart);
    producePending = false;
    paramsRead = false;
}

ExecStreamResult ReshapeExecStream::execute(
    ExecStreamQuantum const &quantum)
{
    if (!paramsRead) {
        readDynamicParams();
        paramsRead = true;
    }

    ExecStreamResult rc = precheckConduitBuffers();
    if (rc != EXECRC_YIELD) {
        return rc;
    }

    if (producePending) {
        if (!pOutAccessor->produceTuple(outputData)) {
            return EXECRC_BUF_OVERFLOW;
        }
        pInAccessor->consumeTuple();
        producePending = false;
    }

    for (uint i = 0; i < quantum.nTuplesMax; i++) {
        if (!pInAccessor->demandData()) {
            return EXECRC_BUF_UNDERFLOW;
        }

        pInAccessor->accessConsumptionTuple();

        // filter the data, if filtering criteria provided
        if (compOp != COMP_NOOP) {
            bool pass = compareInput();
            if (!pass) {
                pInAccessor->consumeTuple();
                continue;
            }
        }

        if (castRequired) {
            castOutput();
        } else {
            outputProjAccessor.unmarshal(outputData);
        }
        producePending = true;
        if (!pOutAccessor->produceTuple(outputData)) {
            return EXECRC_BUF_OVERFLOW;
        }
        producePending = false;
        pInAccessor->consumeTuple();
    }

    return EXECRC_QUANTUM_EXPIRED;
}

void ReshapeExecStream::readDynamicParams()
{
    uint currCompIdx = paramCompareData.size() - numCompDynParams;
    uint currOutputIdx = inputOutputDesc.size();
    for (uint i = 0; i < dynamicParameters.size(); i++) {
        if (!isMAXU(dynamicParameters[i].compareOffset)) {
            TupleDatum const &param =
                pDynamicParamManager->getParam(
                    dynamicParameters[i].dynamicParamId).getDatum();
            paramCompareData[currCompIdx++] = param;
        }
        if (dynamicParameters[i].outputParam) {
            TupleDatum const &param =
                pDynamicParamManager->getParam(
                    dynamicParameters[i].dynamicParamId).getDatum();
            outputData[currOutputIdx++] = param;
        }
    }
}

bool ReshapeExecStream::compareInput()
{
    inputCompareProjAccessor.unmarshal(inputCompareData);
    int rc;

    // if the comparison is non-equality, first compare the first n-1 keys
    // for equality; if those keys are equal, then do the non-equality
    // comparison on just the last key
    if (compOp == COMP_EQ) {
        rc = compTupleDesc.compareTuples(inputCompareData, paramCompareData);
    } else {
        rc =
            compTupleDesc.compareTuplesKey(
                inputCompareData, paramCompareData,
                paramCompareData.size() - 1);
        if (rc != 0) {
            return false;
        }
        // ignore NULLs if doing a comparison against a non-NULL value
        if (!paramCompareData[paramCompareData.size() - 1].pData) {
            rc =
                lastKeyDesc.compareTuples(
                    inputCompareData, lastKey, paramCompareData, lastKey);
        } else {
            bool containsNullKey;
            rc =
                lastKeyDesc.compareTuples(
                    inputCompareData, lastKey, paramCompareData, lastKey,
                    &containsNullKey);
            if (containsNullKey) {
                return false;
            }
        }
    }

    bool pass;
    switch (compOp) {
    case COMP_EQ:
        pass = (rc == 0);
        break;
    case COMP_NE:
        pass = (rc != 0);
        break;
    case COMP_LT:
        pass = (rc < 0);
        break;
    case COMP_LE:
        pass = (rc <= 0);
        break;
    case COMP_GT:
        pass = (rc > 0);
        break;
    case COMP_GE:
        pass = (rc >= 0);
        break;
    default:
        pass = false;
        permAssert(false);
    }
    return pass;
}

void ReshapeExecStream::castOutput()
{
    outputProjAccessor.unmarshal(inputOutputData);
    for (uint i = 0; i < inputOutputData.size(); i++) {
        // truncate value if it exceeds the destination size
        uint len = std::min(
            inputOutputData[i].cbData, outputDesc[i].cbStorage);
        outputData[i].cbData = len;
        if (inputOutputData[i].pData) {
            outputData[i].pData = inputOutputData[i].pData;
        } else {
            outputData[i].pData = NULL;
        }
    }
}

void ReshapeExecStream::closeImpl()
{
    ConduitExecStream::closeImpl();
}

FENNEL_END_CPPFILE("$Id$");

// End ReshapeExecStream.cpp
<commit_msg>FENNEL:  ReshapeExecStream requires Unicode consistency in input/output<commit_after>/*
// $Id$
// Fennel is a library of data storage and processing components.
// Copyright (C) 2005-2007 The Eigenbase Project
// Copyright (C) 2005-2007 Disruptive Tech
// Copyright (C) 2005-2007 LucidEra, Inc.
// Portions Copyright (C) 2004-2007 John V. Sichi
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version approved by The Eigenbase Project.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "fennel/common/CommonPreamble.h"
#include "fennel/tuple/StandardTypeDescriptor.h"
#include "fennel/exec/ExecStreamBufAccessor.h"
#include "fennel/exec/ReshapeExecStream.h"

#include <hash_set>

FENNEL_BEGIN_CPPFILE("$Id$");

void ReshapeExecStream::prepare(ReshapeExecStreamParams const &params)
{
    ConduitExecStream::prepare(params);

    TupleDescriptor const &inputDesc = pInAccessor->getTupleDesc();
    TupleAccessor &inputAccessor = pInAccessor->getConsumptionTupleAccessor();
    dynamicParameters.assign(
        params.dynamicParameters.begin(),
        params.dynamicParameters.end());

    compOp = params.compOp;
    if (compOp != COMP_NOOP) {
        initCompareData(params, inputDesc, inputAccessor);
    }

    // Setup the output projection that projects from the input tuple
    outputProjAccessor.bind(inputAccessor, params.outputProj);
    inputOutputDesc.projectFrom(inputDesc, params.outputProj);

    // Setup the output descriptor and data
    outputDesc = pOutAccessor->getTupleDesc();
    outputData.compute(outputDesc);

    // Determine how many of the dynamic parameters need to be written into
    // the output tuple
    uint numOutputDynParams = 0;
    for (uint i = 0; i < dynamicParameters.size(); i++) {
        if (dynamicParameters[i].outputParam) {
            numOutputDynParams++;
        }
    }

    // Setup the output descriptor and data that excludes dynamic parameters
    // in the output tuple
    assert(inputOutputDesc.size() == outputDesc.size() - numOutputDynParams);
    TupleDescriptor partialOutputDesc;
    if (numOutputDynParams == 0) {
        partialOutputDesc = outputDesc;
    } else if (inputOutputDesc.size() > 0) {
        partialOutputDesc.resize(inputOutputDesc.size());
        std::copy(
            outputDesc.begin(),
            outputDesc.end() - numOutputDynParams,
            partialOutputDesc.begin());
    }

    // determine if simple casting is required
    castRequired = (inputOutputDesc != partialOutputDesc);
    if (castRequired) {
        TupleProjection proj;
        if (compOp == COMP_NE) {
            proj = params.inputCompareProj;
        }
        assert(checkCastTypes(proj, inputOutputDesc, partialOutputDesc));
        inputOutputData.compute(inputOutputDesc);
    }
}

void ReshapeExecStream::initCompareData(
    ReshapeExecStreamParams const &params,
    TupleDescriptor const &inputDesc,
    TupleAccessor const &inputAccessor)
{
    // Setup the comparison tuple descriptor
    assert(params.inputCompareProj.size() > 0);
    TupleProjection inputCompareProj = params.inputCompareProj;
    compTupleDesc.projectFrom(inputDesc, inputCompareProj);
    // Adjust the descriptor to allow NULLs in case we're filtering out NULLs
    for (uint i = 0; i < compTupleDesc.size(); i++) {
        compTupleDesc[i].isNullable = true;
    }

    // Setup the projection of the columns for comparison
    inputCompareProjAccessor.bind(inputAccessor, inputCompareProj);
    inputCompareData.compute(compTupleDesc);

    // Setup a descriptor that excludes the dynamic parameters that will
    // be used in comparisons, if there are dynamic parameters.  The dynamic
    // parameters appear at the end of the descriptor.
    TupleDescriptor partialCompTupleDesc;
    numCompDynParams = 0;
    for (uint i = 0; i < dynamicParameters.size(); i++) {
        if (!isMAXU(dynamicParameters[i].compareOffset)) {
            numCompDynParams++;
        }
    }
    if (numCompDynParams > 0) {
        partialCompTupleDesc.resize(compTupleDesc.size() - numCompDynParams);
        std::copy(
            compTupleDesc.begin(),
            compTupleDesc.end() - numCompDynParams,
            partialCompTupleDesc.begin());
    }

    paramCompareData.compute(compTupleDesc);
    if (numCompDynParams == 0) {
        copyCompareTuple(
            compTupleDesc,
            paramCompareData,
            params.pCompTupleBuffer.get());
    } else if (partialCompTupleDesc.size() > 0) {
        TupleData partialCompareData;
        partialCompareData.compute(partialCompTupleDesc);
        copyCompareTuple(
            partialCompTupleDesc,
            partialCompareData,
            params.pCompTupleBuffer.get());

        // Copy the partial tuple data to the tuple data that will
        // be used in the actual comparisons
        std::copy(
            partialCompareData.begin(),
            partialCompareData.end(),
            paramCompareData.begin());
    }

    // Setup a tuple projection to project the last key for use in
    // non-equality comparisons
    lastKey.push_back(paramCompareData.size() - 1);
    lastKeyDesc.projectFrom(compTupleDesc, lastKey);
}

void ReshapeExecStream::copyCompareTuple(
    TupleDescriptor const &tupleDesc,
    TupleData &tupleData,
    PBuffer tupleBuffer)
{
    TupleAccessor tupleAccessor;
    tupleAccessor.compute(tupleDesc);
    tupleAccessor.setCurrentTupleBuf(tupleBuffer);
    uint nBytes = tupleAccessor.getCurrentByteCount();
    compTupleBuffer.reset(new FixedBuffer[nBytes]);
    memcpy(compTupleBuffer.get(), tupleBuffer, nBytes);
    tupleAccessor.setCurrentTupleBuf(compTupleBuffer.get());
    tupleAccessor.unmarshal(tupleData);
}

bool ReshapeExecStream::checkCastTypes(
    const TupleProjection &compareProj,
    const TupleDescriptor &inputTupleDesc,
    const TupleDescriptor &outputTupleDesc)
{
    for (uint i = 0; i < inputTupleDesc.size(); i++) {
        if (!(inputTupleDesc[i] == outputTupleDesc[i])) {
            // only allow not nullable -> nullable, unless nulls are being
            // filtered out from that column
            if (inputTupleDesc[i].isNullable &&
                !outputTupleDesc[i].isNullable)
            {
                assert(nullFilter(compareProj, i));
            } else {
                assert(
                    (inputTupleDesc[i].isNullable ==
                        outputTupleDesc[i].isNullable)
                    || (!inputTupleDesc[i].isNullable
                        && outputTupleDesc[i].isNullable));
            }
            StoredTypeDescriptor::Ordinal inputType =
                inputTupleDesc[i].pTypeDescriptor->getOrdinal();
            StoredTypeDescriptor::Ordinal outputType =
                outputTupleDesc[i].pTypeDescriptor->getOrdinal();

            // can't convert between unicode and non-unicode;
            // normalize types to non-unicode to make other checks
            // easier, but verify that either both or neither are unicode
            bool inputUnicode = false;
            if (inputType == STANDARD_TYPE_UNICODE_CHAR) {
                inputType = STANDARD_TYPE_CHAR;
                inputUnicode = true;
            }
            if (inputType == STANDARD_TYPE_UNICODE_VARCHAR) {
                inputType = STANDARD_TYPE_VARCHAR;
                inputUnicode = true;
            }

            bool outputUnicode = false;
            if (outputType == STANDARD_TYPE_UNICODE_CHAR) {
                outputType = STANDARD_TYPE_CHAR;
                outputUnicode = true;
            }
            if (outputType == STANDARD_TYPE_UNICODE_VARCHAR) {
                outputType = STANDARD_TYPE_VARCHAR;
                outputUnicode = true;
            }

            if (inputUnicode || outputUnicode) {
                assert(inputUnicode && outputUnicode);
            }

            if (inputType != outputType) {
                // if types are different, must be casting from char to
                // varchar
                assert(
                    (inputType == STANDARD_TYPE_CHAR)
                    && (outputType == STANDARD_TYPE_VARCHAR));
            }
            if (inputTupleDesc[i].cbStorage != outputTupleDesc[i].cbStorage) {
                // if lengths are different, must be casting from char or
                // varchar to varchar
                assert(
                    ((inputType == STANDARD_TYPE_VARCHAR)
                        || (inputType == STANDARD_TYPE_CHAR))
                    && (outputType == STANDARD_TYPE_VARCHAR));
            }
        }
    }
    return true;
}

bool ReshapeExecStream::nullFilter(
    const TupleProjection &compareProj, uint colno)
{
    for (uint i = 0; i < compareProj.size(); i++) {
        if (compareProj[i] == colno) {
            if (!paramCompareData[i].pData) {
                return true;
            } else {
                break;
            }
        }
    }
    return false;
}

void ReshapeExecStream::open(bool restart)
{
    ConduitExecStream::open(restart);
    producePending = false;
    paramsRead = false;
}

ExecStreamResult ReshapeExecStream::execute(
    ExecStreamQuantum const &quantum)
{
    if (!paramsRead) {
        readDynamicParams();
        paramsRead = true;
    }

    ExecStreamResult rc = precheckConduitBuffers();
    if (rc != EXECRC_YIELD) {
        return rc;
    }

    if (producePending) {
        if (!pOutAccessor->produceTuple(outputData)) {
            return EXECRC_BUF_OVERFLOW;
        }
        pInAccessor->consumeTuple();
        producePending = false;
    }

    for (uint i = 0; i < quantum.nTuplesMax; i++) {
        if (!pInAccessor->demandData()) {
            return EXECRC_BUF_UNDERFLOW;
        }

        pInAccessor->accessConsumptionTuple();

        // filter the data, if filtering criteria provided
        if (compOp != COMP_NOOP) {
            bool pass = compareInput();
            if (!pass) {
                pInAccessor->consumeTuple();
                continue;
            }
        }

        if (castRequired) {
            castOutput();
        } else {
            outputProjAccessor.unmarshal(outputData);
        }
        producePending = true;
        if (!pOutAccessor->produceTuple(outputData)) {
            return EXECRC_BUF_OVERFLOW;
        }
        producePending = false;
        pInAccessor->consumeTuple();
    }

    return EXECRC_QUANTUM_EXPIRED;
}

void ReshapeExecStream::readDynamicParams()
{
    uint currCompIdx = paramCompareData.size() - numCompDynParams;
    uint currOutputIdx = inputOutputDesc.size();
    for (uint i = 0; i < dynamicParameters.size(); i++) {
        if (!isMAXU(dynamicParameters[i].compareOffset)) {
            TupleDatum const &param =
                pDynamicParamManager->getParam(
                    dynamicParameters[i].dynamicParamId).getDatum();
            paramCompareData[currCompIdx++] = param;
        }
        if (dynamicParameters[i].outputParam) {
            TupleDatum const &param =
                pDynamicParamManager->getParam(
                    dynamicParameters[i].dynamicParamId).getDatum();
            outputData[currOutputIdx++] = param;
        }
    }
}

bool ReshapeExecStream::compareInput()
{
    inputCompareProjAccessor.unmarshal(inputCompareData);
    int rc;

    // if the comparison is non-equality, first compare the first n-1 keys
    // for equality; if those keys are equal, then do the non-equality
    // comparison on just the last key
    if (compOp == COMP_EQ) {
        rc = compTupleDesc.compareTuples(inputCompareData, paramCompareData);
    } else {
        rc =
            compTupleDesc.compareTuplesKey(
                inputCompareData, paramCompareData,
                paramCompareData.size() - 1);
        if (rc != 0) {
            return false;
        }
        // ignore NULLs if doing a comparison against a non-NULL value
        if (!paramCompareData[paramCompareData.size() - 1].pData) {
            rc =
                lastKeyDesc.compareTuples(
                    inputCompareData, lastKey, paramCompareData, lastKey);
        } else {
            bool containsNullKey;
            rc =
                lastKeyDesc.compareTuples(
                    inputCompareData, lastKey, paramCompareData, lastKey,
                    &containsNullKey);
            if (containsNullKey) {
                return false;
            }
        }
    }

    bool pass;
    switch (compOp) {
    case COMP_EQ:
        pass = (rc == 0);
        break;
    case COMP_NE:
        pass = (rc != 0);
        break;
    case COMP_LT:
        pass = (rc < 0);
        break;
    case COMP_LE:
        pass = (rc <= 0);
        break;
    case COMP_GT:
        pass = (rc > 0);
        break;
    case COMP_GE:
        pass = (rc >= 0);
        break;
    default:
        pass = false;
        permAssert(false);
    }
    return pass;
}

void ReshapeExecStream::castOutput()
{
    outputProjAccessor.unmarshal(inputOutputData);
    for (uint i = 0; i < inputOutputData.size(); i++) {
        // truncate value if it exceeds the destination size
        uint len = std::min(
            inputOutputData[i].cbData, outputDesc[i].cbStorage);
        outputData[i].cbData = len;
        if (inputOutputData[i].pData) {
            outputData[i].pData = inputOutputData[i].pData;
        } else {
            outputData[i].pData = NULL;
        }
    }
}

void ReshapeExecStream::closeImpl()
{
    ConduitExecStream::closeImpl();
}

FENNEL_END_CPPFILE("$Id$");

// End ReshapeExecStream.cpp
<|endoftext|>


<commit_before>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum 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 version 3 for more details.
*/

#include <sstream>
#include <TestSuite/Tester.h>

#include "Math/Constants.h"
#include "Math/DualQuaternion.h"

namespace Magnum { namespace Math { namespace Test {

class DualQuaternionTest: public Corrade::TestSuite::Tester {
    public:
        explicit DualQuaternionTest();

        void construct();
        void constructDefault();
        void constructFromVector();

        void lengthSquared();
        void length();
        void normalized();

        void quaternionConjugated();
        void dualConjugated();
        void conjugated();
        void inverted();

        void rotation();
        void translation();
        void combinedTransformParts();
        void matrix();
        void transformPoint();
        void transformPointNormalized();

        void debug();
};

typedef Math::Dual<float> Dual;
typedef Math::Matrix4<float> Matrix4;
typedef Math::DualQuaternion<float> DualQuaternion;
typedef Math::Quaternion<float> Quaternion;
typedef Math::Vector3<float> Vector3;
typedef Math::Vector4<float> Vector4;

DualQuaternionTest::DualQuaternionTest() {
    addTests(&DualQuaternionTest::construct,
             &DualQuaternionTest::constructDefault,
             &DualQuaternionTest::constructFromVector,

             &DualQuaternionTest::lengthSquared,
             &DualQuaternionTest::length,
             &DualQuaternionTest::normalized,

             &DualQuaternionTest::quaternionConjugated,
             &DualQuaternionTest::dualConjugated,
             &DualQuaternionTest::conjugated,
             &DualQuaternionTest::inverted,

             &DualQuaternionTest::rotation,
             &DualQuaternionTest::translation,
             &DualQuaternionTest::combinedTransformParts,
             &DualQuaternionTest::matrix,
             &DualQuaternionTest::transformPoint,
             &DualQuaternionTest::transformPointNormalized,

             &DualQuaternionTest::debug);
}

void DualQuaternionTest::construct() {
    DualQuaternion q({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f});
    CORRADE_COMPARE(q.real(), Quaternion({1.0f, 2.0f, 3.0f}, -4.0f));
    CORRADE_COMPARE(q.dual(), Quaternion({0.5f, -3.1f, 3.3f}, 2.0f));
}

void DualQuaternionTest::constructDefault() {
    CORRADE_COMPARE(DualQuaternion(), DualQuaternion({{0.0f, 0.0f, 0.0f}, 1.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f}));
}

void DualQuaternionTest::constructFromVector() {
    CORRADE_COMPARE(DualQuaternion({1.0f, 2.0f, 3.0f}), DualQuaternion({{0.0f, 0.0f, 0.0f}, 1.0f}, {{1.0f, 2.0f, 3.0f}, 0.0f}));
}

void DualQuaternionTest::lengthSquared() {
    CORRADE_COMPARE(DualQuaternion().lengthSquared(), 1.0f);

    DualQuaternion a({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.0f, 3.0f}, 2.0f});
    CORRADE_COMPARE(a.lengthSquared(), Dual(30.0f, -9.0f));
}

void DualQuaternionTest::length() {
    CORRADE_COMPARE(DualQuaternion().length(), 1.0f);

    DualQuaternion a({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.0f, 3.0f}, 2.0f});
    CORRADE_COMPARE(a.length(), Dual(5.477226f, -0.821584f));
}

void DualQuaternionTest::normalized() {
    DualQuaternion a({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.0f, 3.0f}, 2.0f});
    DualQuaternion b({{0.182574f, 0.365148f, 0.547723f}, -0.730297f}, {{0.118673f, -0.49295f, 0.629881f}, 0.255604f});
    CORRADE_COMPARE(a.normalized().length(), 1.0f);
    CORRADE_COMPARE(a.normalized(), b);
}

void DualQuaternionTest::quaternionConjugated() {
    DualQuaternion a({{ 1.0f,  2.0f,  3.0f}, -4.0f}, {{ 0.5f, -3.1f,  3.3f}, 2.0f});
    DualQuaternion b({{-1.0f, -2.0f, -3.0f}, -4.0f}, {{-0.5f,  3.1f, -3.3f}, 2.0f});

    CORRADE_COMPARE(a.quaternionConjugated(), b);
}

void DualQuaternionTest::dualConjugated() {
    DualQuaternion a({{1.0f, 2.0f, 3.0f}, -4.0f}, {{ 0.5f, -3.1f,  3.3f},  2.0f});
    DualQuaternion b({{1.0f, 2.0f, 3.0f}, -4.0f}, {{-0.5f,  3.1f, -3.3f}, -2.0f});

    CORRADE_COMPARE(a.dualConjugated(), b);
}

void DualQuaternionTest::conjugated() {
    DualQuaternion a({{ 1.0f,  2.0f,  3.0f}, -4.0f}, {{ 0.5f, -3.1f,  3.3f},  2.0f});
    DualQuaternion b({{-1.0f, -2.0f, -3.0f}, -4.0f}, {{ 0.5f, -3.1f,  3.3f}, -2.0f});

    CORRADE_COMPARE(a.conjugated(), b);
}

void DualQuaternionTest::inverted() {
    DualQuaternion a({{ 1.0f,  2.0f,  3.0f}, -4.0f}, {{ 2.5f, -3.1f,  3.3f},  2.0f});
    DualQuaternion b({{-0.033333f, -0.066667f, -0.1f}, -0.133333f}, {{-0.087333f, 0.095333f, -0.122f}, 0.050667f});

    CORRADE_COMPARE(a*a.inverted(), DualQuaternion());
    CORRADE_COMPARE(a.inverted(), b);
}

void DualQuaternionTest::rotation() {
    std::ostringstream o;
    Error::setOutput(&o);

    float angle = deg(120.0f);
    Vector3 axis(1.0f/Constants<float>::sqrt3());

    CORRADE_COMPARE(DualQuaternion::rotation(angle, axis*2.0f), DualQuaternion());
    CORRADE_COMPARE(o.str(), "Math::Quaternion::rotation(): axis must be normalized\n");

    DualQuaternion q = DualQuaternion::rotation(angle, axis);
    CORRADE_COMPARE(q, DualQuaternion({Vector3(0.5f, 0.5f, 0.5f), 0.5f}, {{}, 0.0f}));
    CORRADE_COMPARE(q.rotationAngle(), angle);
    CORRADE_COMPARE(q.rotationAxis(), axis);
}

void DualQuaternionTest::translation() {
    Vector3 vec(1.0f, -3.5f, 0.5f);
    DualQuaternion q = DualQuaternion::translation(vec);
    CORRADE_COMPARE(q, DualQuaternion({}, {{0.5f, -1.75f, 0.25f}, 0.0f}));
    CORRADE_COMPARE(q.translation(), vec);
}

void DualQuaternionTest::combinedTransformParts() {
    Vector3 translation = Vector3(-1.0f, 2.0f, 3.0f);
    DualQuaternion a = DualQuaternion::translation(translation)*DualQuaternion::rotation(deg(23.0f), Vector3::xAxis());
    DualQuaternion b = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation(translation);

    CORRADE_COMPARE(a.rotationAxis(), Vector3::xAxis());
    CORRADE_COMPARE(b.rotationAxis(), Vector3::xAxis());
    CORRADE_COMPARE(a.rotationAngle(), deg(23.0f));
    CORRADE_COMPARE(b.rotationAngle(), deg(23.0f));

    CORRADE_COMPARE(a.translation(), translation);
    CORRADE_COMPARE(b.translation(), Quaternion::rotation(deg(23.0f), Vector3::xAxis()).rotateVectorNormalized(translation));
}

void DualQuaternionTest::matrix() {
    DualQuaternion q = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
    Matrix4 m = Matrix4::rotationX(deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});

    /* Verify that negated dual quaternion gives the same transformation */
    CORRADE_COMPARE(q.matrix(), m);
    CORRADE_COMPARE((-q).matrix(), m);
}

void DualQuaternionTest::transformPoint() {
    DualQuaternion a = DualQuaternion::translation({-1.0f, 2.0f, 3.0f})*DualQuaternion::rotation(deg(23.0f), Vector3::xAxis());
    DualQuaternion b = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
    Matrix4 m = Matrix4::translation({-1.0f, 2.0f, 3.0f})*Matrix4::rotationX(deg(23.0f));
    Matrix4 n = Matrix4::rotationX(deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});
    Vector3 v(0.0f, -3.6f, 0.7f);

    Vector3 transformedA = (a*Dual(2)).transformPoint(v);
    CORRADE_COMPARE(transformedA, m.transformPoint(v));
    CORRADE_COMPARE(transformedA, Vector3(-1.0f, -1.58733f, 2.237721f));

    Vector3 transformedB = (b*Dual(2)).transformPoint(v);
    CORRADE_COMPARE(transformedB, n.transformPoint(v));
    CORRADE_COMPARE(transformedB, Vector3(-1.0f, -2.918512f, 2.780698f));
}

void DualQuaternionTest::transformPointNormalized() {
    DualQuaternion a = DualQuaternion::translation({-1.0f, 2.0f, 3.0f})*DualQuaternion::rotation(deg(23.0f), Vector3::xAxis());
    DualQuaternion b = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
    Matrix4 m = Matrix4::translation({-1.0f, 2.0f, 3.0f})*Matrix4::rotationX(deg(23.0f));
    Matrix4 n = Matrix4::rotationX(deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});
    Vector3 v(0.0f, -3.6f, 0.7f);

    std::ostringstream o;
    Corrade::Utility::Error::setOutput(&o);
    Vector3 notTransformed = (a*Dual(2)).transformPointNormalized(v);
    CORRADE_VERIFY(notTransformed != notTransformed);
    CORRADE_COMPARE(o.str(), "Math::DualQuaternion::transformPointNormalized(): dual quaternion must be normalized\n");

    Vector3 transformedA = a.transformPointNormalized(v);
    CORRADE_COMPARE(transformedA, m.transformPoint(v));
    CORRADE_COMPARE(transformedA, Vector3(-1.0f, -1.58733f, 2.237721f));

    Vector3 transformedB = b.transformPointNormalized(v);
    CORRADE_COMPARE(transformedB, n.transformPoint(v));
    CORRADE_COMPARE(transformedB, Vector3(-1.0f, -2.918512f, 2.780698f));
}

void DualQuaternionTest::debug() {
    std::ostringstream o;

    Debug(&o) << DualQuaternion({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f});
    CORRADE_COMPARE(o.str(), "DualQuaternion({{1, 2, 3}, -4}, {{0.5, -3.1, 3.3}, 2})\n");
}

}}}

CORRADE_TEST_MAIN(Magnum::Math::Test::DualQuaternionTest)
<commit_msg>Math: test constexpr methods on DualQuaternion.<commit_after>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

    Magnum is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License version 3
    only, as published by the Free Software Foundation.

    Magnum 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 version 3 for more details.
*/

#include <sstream>
#include <TestSuite/Tester.h>

#include "Math/Constants.h"
#include "Math/DualQuaternion.h"

namespace Magnum { namespace Math { namespace Test {

class DualQuaternionTest: public Corrade::TestSuite::Tester {
    public:
        explicit DualQuaternionTest();

        void construct();
        void constructDefault();
        void constructFromVector();

        void constExpressions();

        void lengthSquared();
        void length();
        void normalized();

        void quaternionConjugated();
        void dualConjugated();
        void conjugated();
        void inverted();

        void rotation();
        void translation();
        void combinedTransformParts();
        void matrix();
        void transformPoint();
        void transformPointNormalized();

        void debug();
};

typedef Math::Dual<float> Dual;
typedef Math::Matrix4<float> Matrix4;
typedef Math::DualQuaternion<float> DualQuaternion;
typedef Math::Quaternion<float> Quaternion;
typedef Math::Vector3<float> Vector3;
typedef Math::Vector4<float> Vector4;

DualQuaternionTest::DualQuaternionTest() {
    addTests(&DualQuaternionTest::construct,
             &DualQuaternionTest::constructDefault,
             &DualQuaternionTest::constructFromVector,

             &DualQuaternionTest::constExpressions,

             &DualQuaternionTest::lengthSquared,
             &DualQuaternionTest::length,
             &DualQuaternionTest::normalized,

             &DualQuaternionTest::quaternionConjugated,
             &DualQuaternionTest::dualConjugated,
             &DualQuaternionTest::conjugated,
             &DualQuaternionTest::inverted,

             &DualQuaternionTest::rotation,
             &DualQuaternionTest::translation,
             &DualQuaternionTest::combinedTransformParts,
             &DualQuaternionTest::matrix,
             &DualQuaternionTest::transformPoint,
             &DualQuaternionTest::transformPointNormalized,

             &DualQuaternionTest::debug);
}

void DualQuaternionTest::construct() {
    DualQuaternion q({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f});
    CORRADE_COMPARE(q.real(), Quaternion({1.0f, 2.0f, 3.0f}, -4.0f));
    CORRADE_COMPARE(q.dual(), Quaternion({0.5f, -3.1f, 3.3f}, 2.0f));
}

void DualQuaternionTest::constructDefault() {
    CORRADE_COMPARE(DualQuaternion(), DualQuaternion({{0.0f, 0.0f, 0.0f}, 1.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f}));
}

void DualQuaternionTest::constructFromVector() {
    CORRADE_COMPARE(DualQuaternion({1.0f, 2.0f, 3.0f}), DualQuaternion({{0.0f, 0.0f, 0.0f}, 1.0f}, {{1.0f, 2.0f, 3.0f}, 0.0f}));
}

void DualQuaternionTest::constExpressions() {
    /* Default constructor */
    constexpr DualQuaternion a;
    CORRADE_COMPARE(a, DualQuaternion({{0.0f, 0.0f, 0.0f}, 1.0f}, {{0.0f, 0.0f, 0.0f}, 0.0f}));

    /* Value constructor */
    constexpr DualQuaternion b({{1.0f, 2.0f, -3.0f}, -3.5f}, {{4.5f, -7.0f, 2.0f}, 1.0f});
    CORRADE_COMPARE(b, DualQuaternion({{1.0f, 2.0f, -3.0f}, -3.5f}, {{4.5f, -7.0f, 2.0f}, 1.0f}));

    /* Vector constructor */
    constexpr DualQuaternion c({1.5f, -5.0f, 3.0f});
    CORRADE_COMPARE(c, DualQuaternion({{0.0f, 0.0f, 0.0f}, 1.0f}, {{1.5f, -5.0f, 3.0f}, 0.0f}));

    /* Copy constructor */
    constexpr DualQuaternion d(b);
    CORRADE_COMPARE(d, DualQuaternion({{1.0f, 2.0f, -3.0f}, -3.5f}, {{4.5f, -7.0f, 2.0f}, 1.0f}));
}

void DualQuaternionTest::lengthSquared() {
    CORRADE_COMPARE(DualQuaternion().lengthSquared(), 1.0f);

    DualQuaternion a({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.0f, 3.0f}, 2.0f});
    CORRADE_COMPARE(a.lengthSquared(), Dual(30.0f, -9.0f));
}

void DualQuaternionTest::length() {
    CORRADE_COMPARE(DualQuaternion().length(), 1.0f);

    DualQuaternion a({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.0f, 3.0f}, 2.0f});
    CORRADE_COMPARE(a.length(), Dual(5.477226f, -0.821584f));
}

void DualQuaternionTest::normalized() {
    DualQuaternion a({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.0f, 3.0f}, 2.0f});
    DualQuaternion b({{0.182574f, 0.365148f, 0.547723f}, -0.730297f}, {{0.118673f, -0.49295f, 0.629881f}, 0.255604f});
    CORRADE_COMPARE(a.normalized().length(), 1.0f);
    CORRADE_COMPARE(a.normalized(), b);
}

void DualQuaternionTest::quaternionConjugated() {
    DualQuaternion a({{ 1.0f,  2.0f,  3.0f}, -4.0f}, {{ 0.5f, -3.1f,  3.3f}, 2.0f});
    DualQuaternion b({{-1.0f, -2.0f, -3.0f}, -4.0f}, {{-0.5f,  3.1f, -3.3f}, 2.0f});

    CORRADE_COMPARE(a.quaternionConjugated(), b);
}

void DualQuaternionTest::dualConjugated() {
    DualQuaternion a({{1.0f, 2.0f, 3.0f}, -4.0f}, {{ 0.5f, -3.1f,  3.3f},  2.0f});
    DualQuaternion b({{1.0f, 2.0f, 3.0f}, -4.0f}, {{-0.5f,  3.1f, -3.3f}, -2.0f});

    CORRADE_COMPARE(a.dualConjugated(), b);
}

void DualQuaternionTest::conjugated() {
    DualQuaternion a({{ 1.0f,  2.0f,  3.0f}, -4.0f}, {{ 0.5f, -3.1f,  3.3f},  2.0f});
    DualQuaternion b({{-1.0f, -2.0f, -3.0f}, -4.0f}, {{ 0.5f, -3.1f,  3.3f}, -2.0f});

    CORRADE_COMPARE(a.conjugated(), b);
}

void DualQuaternionTest::inverted() {
    DualQuaternion a({{ 1.0f,  2.0f,  3.0f}, -4.0f}, {{ 2.5f, -3.1f,  3.3f},  2.0f});
    DualQuaternion b({{-0.033333f, -0.066667f, -0.1f}, -0.133333f}, {{-0.087333f, 0.095333f, -0.122f}, 0.050667f});

    CORRADE_COMPARE(a*a.inverted(), DualQuaternion());
    CORRADE_COMPARE(a.inverted(), b);
}

void DualQuaternionTest::rotation() {
    std::ostringstream o;
    Error::setOutput(&o);

    float angle = deg(120.0f);
    Vector3 axis(1.0f/Constants<float>::sqrt3());

    CORRADE_COMPARE(DualQuaternion::rotation(angle, axis*2.0f), DualQuaternion());
    CORRADE_COMPARE(o.str(), "Math::Quaternion::rotation(): axis must be normalized\n");

    DualQuaternion q = DualQuaternion::rotation(angle, axis);
    CORRADE_COMPARE(q, DualQuaternion({Vector3(0.5f, 0.5f, 0.5f), 0.5f}, {{}, 0.0f}));
    CORRADE_COMPARE(q.rotationAngle(), angle);
    CORRADE_COMPARE(q.rotationAxis(), axis);
}

void DualQuaternionTest::translation() {
    Vector3 vec(1.0f, -3.5f, 0.5f);
    DualQuaternion q = DualQuaternion::translation(vec);
    CORRADE_COMPARE(q, DualQuaternion({}, {{0.5f, -1.75f, 0.25f}, 0.0f}));
    CORRADE_COMPARE(q.translation(), vec);
}

void DualQuaternionTest::combinedTransformParts() {
    Vector3 translation = Vector3(-1.0f, 2.0f, 3.0f);
    DualQuaternion a = DualQuaternion::translation(translation)*DualQuaternion::rotation(deg(23.0f), Vector3::xAxis());
    DualQuaternion b = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation(translation);

    CORRADE_COMPARE(a.rotationAxis(), Vector3::xAxis());
    CORRADE_COMPARE(b.rotationAxis(), Vector3::xAxis());
    CORRADE_COMPARE(a.rotationAngle(), deg(23.0f));
    CORRADE_COMPARE(b.rotationAngle(), deg(23.0f));

    CORRADE_COMPARE(a.translation(), translation);
    CORRADE_COMPARE(b.translation(), Quaternion::rotation(deg(23.0f), Vector3::xAxis()).rotateVectorNormalized(translation));
}

void DualQuaternionTest::matrix() {
    DualQuaternion q = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
    Matrix4 m = Matrix4::rotationX(deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});

    /* Verify that negated dual quaternion gives the same transformation */
    CORRADE_COMPARE(q.matrix(), m);
    CORRADE_COMPARE((-q).matrix(), m);
}

void DualQuaternionTest::transformPoint() {
    DualQuaternion a = DualQuaternion::translation({-1.0f, 2.0f, 3.0f})*DualQuaternion::rotation(deg(23.0f), Vector3::xAxis());
    DualQuaternion b = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
    Matrix4 m = Matrix4::translation({-1.0f, 2.0f, 3.0f})*Matrix4::rotationX(deg(23.0f));
    Matrix4 n = Matrix4::rotationX(deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});
    Vector3 v(0.0f, -3.6f, 0.7f);

    Vector3 transformedA = (a*Dual(2)).transformPoint(v);
    CORRADE_COMPARE(transformedA, m.transformPoint(v));
    CORRADE_COMPARE(transformedA, Vector3(-1.0f, -1.58733f, 2.237721f));

    Vector3 transformedB = (b*Dual(2)).transformPoint(v);
    CORRADE_COMPARE(transformedB, n.transformPoint(v));
    CORRADE_COMPARE(transformedB, Vector3(-1.0f, -2.918512f, 2.780698f));
}

void DualQuaternionTest::transformPointNormalized() {
    DualQuaternion a = DualQuaternion::translation({-1.0f, 2.0f, 3.0f})*DualQuaternion::rotation(deg(23.0f), Vector3::xAxis());
    DualQuaternion b = DualQuaternion::rotation(deg(23.0f), Vector3::xAxis())*DualQuaternion::translation({-1.0f, 2.0f, 3.0f});
    Matrix4 m = Matrix4::translation({-1.0f, 2.0f, 3.0f})*Matrix4::rotationX(deg(23.0f));
    Matrix4 n = Matrix4::rotationX(deg(23.0f))*Matrix4::translation({-1.0f, 2.0f, 3.0f});
    Vector3 v(0.0f, -3.6f, 0.7f);

    std::ostringstream o;
    Corrade::Utility::Error::setOutput(&o);
    Vector3 notTransformed = (a*Dual(2)).transformPointNormalized(v);
    CORRADE_VERIFY(notTransformed != notTransformed);
    CORRADE_COMPARE(o.str(), "Math::DualQuaternion::transformPointNormalized(): dual quaternion must be normalized\n");

    Vector3 transformedA = a.transformPointNormalized(v);
    CORRADE_COMPARE(transformedA, m.transformPoint(v));
    CORRADE_COMPARE(transformedA, Vector3(-1.0f, -1.58733f, 2.237721f));

    Vector3 transformedB = b.transformPointNormalized(v);
    CORRADE_COMPARE(transformedB, n.transformPoint(v));
    CORRADE_COMPARE(transformedB, Vector3(-1.0f, -2.918512f, 2.780698f));
}

void DualQuaternionTest::debug() {
    std::ostringstream o;

    Debug(&o) << DualQuaternion({{1.0f, 2.0f, 3.0f}, -4.0f}, {{0.5f, -3.1f, 3.3f}, 2.0f});
    CORRADE_COMPARE(o.str(), "DualQuaternion({{1, 2, 3}, -4}, {{0.5, -3.1, 3.3}, 2})\n");
}

}}}

CORRADE_TEST_MAIN(Magnum::Math::Test::DualQuaternionTest)
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Jari Saukkonen
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <Arduino.h>

#include "HubConfiguration.h"
#include "KomaHubPins.h"
#include "PowerOutputs.h"

#define PWM_CYCLE_LENGTH_MS 100

HubConfiguration* PowerOutputs::hubConfiguration;

static bool pwmState(const HubConfiguration::State& state, int pin) {
    if ((state.relayIsOpenBits & (1 << pin)) == 0) {
        return false;
    }

    int duty = state.pwmPercentages[pin];
    int cycleOffset = pin * PWM_CYCLE_LENGTH_MS / 6;
    int pos = 100 * ((millis() + cycleOffset) % PWM_CYCLE_LENGTH_MS) / PWM_CYCLE_LENGTH_MS;
    return (pos < duty);
}

void PowerOutputs::init(HubConfiguration* hubConfiguration) {
    PowerOutputs::hubConfiguration = hubConfiguration;
    pinMode(11, OUTPUT);
}

void PowerOutputs::loop() {
    const HubConfiguration::FactoryConfig& factoryConfig = hubConfiguration->getFactoryConfig();
    const HubConfiguration::State& state = hubConfiguration->getState();
    int outputPins[] = { KomaHub::P1, KomaHub::P2, KomaHub::P3, KomaHub::P4, KomaHub::P5, KomaHub::P6 };
    for (int pin = 0; pin < factoryConfig.numberOfOutputs; pin++) {
        if ((state.relayIsPwmBits & (1 << pin)) != 0 &&
            (state.pwmIsFastBits & (1 << pin)) == 0) {
            digitalWrite(outputPins[pin], pwmState(state, pin));
            if (pin == 0)
                digitalWrite(11, pwmState(state, pin) ? HIGH : LOW);
        } else {
            digitalWrite(outputPins[pin], (state.relayIsOpenBits & (1 << pin)) != 0 ? HIGH : LOW);
            if (pin == 0)
                digitalWrite(11, (state.relayIsOpenBits & (1 << pin)) != 0 ? HIGH : LOW);
          }
    }
}
<commit_msg>Remove LED debugging code<commit_after>/*
 * Copyright (c) 2016 Jari Saukkonen
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#include <Arduino.h>

#include "HubConfiguration.h"
#include "KomaHubPins.h"
#include "PowerOutputs.h"

#define PWM_CYCLE_LENGTH_MS 100

HubConfiguration* PowerOutputs::hubConfiguration;

static bool pwmState(const HubConfiguration::State& state, int pin) {
    if ((state.relayIsOpenBits & (1 << pin)) == 0) {
        return false;
    }

    int duty = state.pwmPercentages[pin];
    int cycleOffset = pin * PWM_CYCLE_LENGTH_MS / 6;
    int pos = 100 * ((millis() + cycleOffset) % PWM_CYCLE_LENGTH_MS) / PWM_CYCLE_LENGTH_MS;
    return (pos < duty);
}

void PowerOutputs::init(HubConfiguration* hubConfiguration) {
    PowerOutputs::hubConfiguration = hubConfiguration;
}

void PowerOutputs::loop() {
    const HubConfiguration::FactoryConfig& factoryConfig = hubConfiguration->getFactoryConfig();
    const HubConfiguration::State& state = hubConfiguration->getState();

    int outputPins[] = { KomaHub::P1, KomaHub::P2, KomaHub::P3, KomaHub::P4, KomaHub::P5, KomaHub::P6 };
    for (int pin = 0; pin < factoryConfig.numberOfOutputs; pin++) {
        if ((state.relayIsPwmBits & (1 << pin)) != 0 &&
            (state.pwmIsFastBits & (1 << pin)) == 0) {
            digitalWrite(outputPins[pin], pwmState(state, pin));
        } else {
            digitalWrite(outputPins[pin], (state.relayIsOpenBits & (1 << pin)) != 0 ? HIGH : LOW);
        }
    }
}
<|endoftext|>


<commit_before>/***************************************************************************
 *   Copyright (c) 2016 WandererFan <wandererfan@gmail.com>                *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
# include <sstream>
# include <cstring>
# include <cstdlib>
# include <exception>
# include <boost/regex.hpp>
# include <QString>
# include <QStringList>
# include <QRegExp>
# include <QMessageBox>
#include <QRectF>

#endif

#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/FeaturePython.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Parameter.h>
#include <Base/Type.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
#include <Gui/Control.h>
#include <Gui/Document.h>
#include <Gui/Selection.h>
#include <Gui/MainWindow.h>

#include <Mod/Part/App/PartFeature.h>
#include <Mod/Part/App/Part2DObject.h>
#include <Mod/Spreadsheet/App/Sheet.h>

#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/Geometry.h>

#include "QGVPage.h"
#include "MDIViewPage.h"
#include "ViewProviderPage.h"
#include "DrawGuiUtil.h"

using namespace TechDrawGui;

//===========================================================================
// validate helper routines
//===========================================================================

//find a page in Selection, Document or CurrentWindow.
TechDraw::DrawPage* DrawGuiUtil::findPage(Gui::Command* cmd)
{
    TechDraw::DrawPage* page;
    int failCase = 0;

    //check Selection and/or Document for a DrawPage
    std::vector<App::DocumentObject*> selPages = cmd->getSelection().getObjectsOfType(TechDraw::DrawPage::getClassTypeId());
    if (selPages.empty()) {                                            //no page in selection
        selPages = cmd->getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId());
        if (selPages.empty()) {                                        //no page in document
            page = nullptr;
            failCase = 1;
        } else if (selPages.size() > 1) {                              //multiple pages in document, but none selected
            page = nullptr;
            failCase = 2;
        } else {                                                       //only page in document - use it
            page = static_cast<TechDraw::DrawPage*>(selPages.front());
        }
    } else if (selPages.size() > 1) {                                  //multiple pages in selection
        page = nullptr;
        failCase = 3;
    } else {                                                           //use only page in selection
        page = static_cast<TechDraw::DrawPage*>(selPages.front());
    }

    //if no page is selected
    //default to currently displayed DrawPage is there is one         //code moved Coverity CID 174668
    if (page == nullptr) {
        if ((failCase == 1) ||
            (failCase == 2)) {
            Gui::MainWindow* w = Gui::getMainWindow();
            Gui::MDIView* mv = w->activeWindow();
            MDIViewPage* mvp = dynamic_cast<MDIViewPage*>(mv);
            if (mvp) {
                QString windowTitle = mvp->windowTitle();
                QGVPage* qp = mvp->getQGVPage();
                page = qp->getDrawPage();
            } else {
                failCase = 1;
            }
        }
    }

    if ((page == nullptr)
        ) {
        switch(failCase) {
            case 1:
                QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No page found"),
                                    QObject::tr("Create/select a page first."));
                break;
            case 2:
                QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Which page?"),
                                     QObject::tr("Can not determine correct page."));
                break;
            case 3:
                QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Too many pages"),
                                     QObject::tr("Select exactly 1 page."));
        }
    }

    return page;
}

bool DrawGuiUtil::needPage(Gui::Command* cmd)
{
    //need a Document and a Page
    bool active = false;
    if (cmd->hasActiveDocument()) {
        auto drawPageType( TechDraw::DrawPage::getClassTypeId() );
        auto selPages = cmd->getDocument()->getObjectsOfType(drawPageType);
        if (!selPages.empty()) {
            active = true;
        }
    }
    return active;
}

bool DrawGuiUtil::needView(Gui::Command* cmd, bool partOnly)
{
    bool haveView = false;
    if (cmd->hasActiveDocument()) {
        if (partOnly) {
            auto drawPartType (TechDraw::DrawViewPart::getClassTypeId());
            auto selParts = cmd->getDocument()->getObjectsOfType(drawPartType);
            if (!selParts.empty()) {
                haveView = true;
            }
        } else {
            auto drawViewType (TechDraw::DrawView::getClassTypeId());
            auto selParts = cmd->getDocument()->getObjectsOfType(drawViewType);
            if (!selParts.empty()) {
                haveView = true;
            }
        }
    }
    return haveView;
}

void DrawGuiUtil::dumpRectF(const char* text, const QRectF& r)
{
    Base::Console().Message("DUMP - dumpRectF - %s\n",text);
    double left = r.left();
    double right = r.right();
    double top = r.top();
    double bottom = r.bottom();
    Base::Console().Message("Extents: L: %.3f, R: %.3f, T: %.3f, B: %.3f\n",left,right,top,bottom);
    Base::Console().Message("Size: W: %.3f H: %.3f\n",r.width(),r.height());
    Base::Console().Message("Centre: (%.3f, %.3f)\n",r.center().x(),r.center().y());
}

void DrawGuiUtil::dumpPointF(const char* text, const QPointF& p)
{
    Base::Console().Message("DUMP - dumpPointF - %s\n",text);
    Base::Console().Message("Point: (%.3f, %.3f)\n",p.x(),p.y());
}
<commit_msg>fix -Wparentheses-equality<commit_after>/***************************************************************************
 *   Copyright (c) 2016 WandererFan <wandererfan@gmail.com>                *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "PreCompiled.h"

#ifndef _PreComp_
# include <sstream>
# include <cstring>
# include <cstdlib>
# include <exception>
# include <boost/regex.hpp>
# include <QString>
# include <QStringList>
# include <QRegExp>
# include <QMessageBox>
#include <QRectF>

#endif

#include <App/Application.h>
#include <App/Document.h>
#include <App/DocumentObject.h>
#include <App/FeaturePython.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Parameter.h>
#include <Base/Type.h>
#include <Gui/Application.h>
#include <Gui/BitmapFactory.h>
#include <Gui/Command.h>
#include <Gui/Control.h>
#include <Gui/Document.h>
#include <Gui/Selection.h>
#include <Gui/MainWindow.h>

#include <Mod/Part/App/PartFeature.h>
#include <Mod/Part/App/Part2DObject.h>
#include <Mod/Spreadsheet/App/Sheet.h>

#include <Mod/TechDraw/App/DrawPage.h>
#include <Mod/TechDraw/App/DrawViewPart.h>
#include <Mod/TechDraw/App/DrawUtil.h>
#include <Mod/TechDraw/App/Geometry.h>

#include "QGVPage.h"
#include "MDIViewPage.h"
#include "ViewProviderPage.h"
#include "DrawGuiUtil.h"

using namespace TechDrawGui;

//===========================================================================
// validate helper routines
//===========================================================================

//find a page in Selection, Document or CurrentWindow.
TechDraw::DrawPage* DrawGuiUtil::findPage(Gui::Command* cmd)
{
    TechDraw::DrawPage* page;
    int failCase = 0;

    //check Selection and/or Document for a DrawPage
    std::vector<App::DocumentObject*> selPages = cmd->getSelection().getObjectsOfType(TechDraw::DrawPage::getClassTypeId());
    if (selPages.empty()) {                                            //no page in selection
        selPages = cmd->getDocument()->getObjectsOfType(TechDraw::DrawPage::getClassTypeId());
        if (selPages.empty()) {                                        //no page in document
            page = nullptr;
            failCase = 1;
        } else if (selPages.size() > 1) {                              //multiple pages in document, but none selected
            page = nullptr;
            failCase = 2;
        } else {                                                       //only page in document - use it
            page = static_cast<TechDraw::DrawPage*>(selPages.front());
        }
    } else if (selPages.size() > 1) {                                  //multiple pages in selection
        page = nullptr;
        failCase = 3;
    } else {                                                           //use only page in selection
        page = static_cast<TechDraw::DrawPage*>(selPages.front());
    }

    //if no page is selected
    //default to currently displayed DrawPage is there is one         //code moved Coverity CID 174668
    if (page == nullptr) {
        if ((failCase == 1) ||
            (failCase == 2)) {
            Gui::MainWindow* w = Gui::getMainWindow();
            Gui::MDIView* mv = w->activeWindow();
            MDIViewPage* mvp = dynamic_cast<MDIViewPage*>(mv);
            if (mvp) {
                QString windowTitle = mvp->windowTitle();
                QGVPage* qp = mvp->getQGVPage();
                page = qp->getDrawPage();
            } else {
                failCase = 1;
            }
        }
    }

    if (page == nullptr) {
        switch(failCase) {
            case 1:
                QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No page found"),
                                    QObject::tr("Create/select a page first."));
                break;
            case 2:
                QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Which page?"),
                                     QObject::tr("Can not determine correct page."));
                break;
            case 3:
                QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Too many pages"),
                                     QObject::tr("Select exactly 1 page."));
        }
    }

    return page;
}

bool DrawGuiUtil::needPage(Gui::Command* cmd)
{
    //need a Document and a Page
    bool active = false;
    if (cmd->hasActiveDocument()) {
        auto drawPageType( TechDraw::DrawPage::getClassTypeId() );
        auto selPages = cmd->getDocument()->getObjectsOfType(drawPageType);
        if (!selPages.empty()) {
            active = true;
        }
    }
    return active;
}

bool DrawGuiUtil::needView(Gui::Command* cmd, bool partOnly)
{
    bool haveView = false;
    if (cmd->hasActiveDocument()) {
        if (partOnly) {
            auto drawPartType (TechDraw::DrawViewPart::getClassTypeId());
            auto selParts = cmd->getDocument()->getObjectsOfType(drawPartType);
            if (!selParts.empty()) {
                haveView = true;
            }
        } else {
            auto drawViewType (TechDraw::DrawView::getClassTypeId());
            auto selParts = cmd->getDocument()->getObjectsOfType(drawViewType);
            if (!selParts.empty()) {
                haveView = true;
            }
        }
    }
    return haveView;
}

void DrawGuiUtil::dumpRectF(const char* text, const QRectF& r)
{
    Base::Console().Message("DUMP - dumpRectF - %s\n",text);
    double left = r.left();
    double right = r.right();
    double top = r.top();
    double bottom = r.bottom();
    Base::Console().Message("Extents: L: %.3f, R: %.3f, T: %.3f, B: %.3f\n",left,right,top,bottom);
    Base::Console().Message("Size: W: %.3f H: %.3f\n",r.width(),r.height());
    Base::Console().Message("Centre: (%.3f, %.3f)\n",r.center().x(),r.center().y());
}

void DrawGuiUtil::dumpPointF(const char* text, const QPointF& p)
{
    Base::Console().Message("DUMP - dumpPointF - %s\n",text);
    Base::Console().Message("Point: (%.3f, %.3f)\n",p.x(),p.y());
}
<|endoftext|>


<commit_before><commit_msg>Fix #3763 Page Tab not removed on undo<commit_after><|endoftext|>