<commit_before>/*************************************************************************/
/* Copyright (c) 2012                                                    */
/* Linas Vepstas <linasvepstas@gmail.com>                                */
/* All rights reserved                                                   */
/*                                                                       */
/*************************************************************************/

/// This file provides a unit test for the operation of the viterbi parser.

#include <stdlib.h>

#include <iostream>

#include <link-grammar/link-includes.h>
#include "read-dict.h"

#include "parser.h"

using namespace std;
using namespace link_grammar::viterbi;

#define Lynk link_grammar::viterbi::Link

#define ANODE(TYPE,NAME) (new Node(TYPE,NAME))
#define ALINK1(TYPE,A) (new Lynk(TYPE, A))
#define ALINK2(TYPE,A,B) (new Lynk(TYPE, A,B))
#define ALINK3(TYPE,A,B,C) (new Lynk(TYPE, A,B,C))

int total_tests = 0;

// ==================================================================
// A simple hello test; several different dictionaries
// should give exactly the same output.  The input sentence
// is just one word, it should connect to the left-wall in
// just one way.
bool test_hello(const char *id, const char *dict_str)
{
	total_tests++;

	Dictionary dict = dictionary_create_from_utf8(dict_str);

	// print_dictionary_data(dict);

	Parser parser(dict);
	parser.streamin("Hello");

	// This is the expected output, no matter what the
	// dictionary may be.
	Lynk* ans =
	ALINK1(SET,
		ALINK3(LING,
			ANODE(LING_TYPE, "Wd"),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "LEFT-WALL"),
				ANODE(CONNECTOR, "Wd+")
			),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "Hello"),
				ANODE(CONNECTOR, "Wd-")
			)
		)
	);

	Lynk* output = parser.get_output_set();
	if (not (ans->operator==(output)))
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "=== Expecting:\n" << ans << endl;
		cout << "=== Got:\n" << output << endl;
		return false;
	}

	Lynk* final_state = parser.get_state();
	if (0 != final_state->get_arity())
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "Expecting the final state to be the empty set, but found:\n"
		     << final_state << endl;
		return false;
	}

	cout<<"PASS: test_hello(" << id << ") " << endl;
	return true;
}

bool test_simplest()
{
	return test_hello ("test_simplest",
		"LEFT-WALL: Wd+;"
		"Hello: Wd-;"
	);
}

bool test_simple_left_disj()
{
	return test_hello ("simple left disj",
		"LEFT-WALL: Wd+ or Wi+ or Wq+;"
		"Hello: Wd-;"
	);
}

bool test_simple_optional_left_cset()
{
	return test_hello ("optional left cset",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {CP+} & {Xx+} & {RW+ or Xp+};"
		"Hello: Wd-;"
	);
}

bool test_simple_right_disj()
{
	return test_hello ("simple right disj",
		"LEFT-WALL: Wd+;"
		"Hello: Wd- or Wi-;"
	);
}

bool test_simple_optional()
{
	return test_hello ("optionals in both csets",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {CP+} & {Xx+} & {RW+ or Xp+};"
		"Hello: Wd- or Xi- or (Xj- & {A+ or B+});"
	);
}

bool test_simple_onereq()
{
	return test_hello ("one required link (simple)",
		"LEFT-WALL: Wd+ or Wi+ or Wq+;"
		"Hello: Wd- & {A+} & {B+} & {C+};"
	);
}

bool test_simple_zeroreq()
{
	return test_hello ("zero required links (simple)",
		"LEFT-WALL: Wd+ or Wi+ or Wq+;"
		"Hello: {Wd-} & {A+} & {B+} & {C+};"
	);
}

int ntest_simple()
{
	size_t num_failures = 0;

	if (!test_simplest()) num_failures++;
	if (!test_simple_left_disj()) num_failures++;
	if (!test_simple_optional_left_cset()) num_failures++;
	if (!test_simple_right_disj()) num_failures++;
	if (!test_simple_optional()) num_failures++;
	if (!test_simple_onereq()) num_failures++;
	if (!test_simple_zeroreq()) num_failures++;
	return num_failures;
}

// ==================================================================
// A test of two alternative parses of a sentence with single word in it.
// Expect to get back a set with two alternative parses, each parse is
// assigned a probability of 1/2.

bool test_alternative(const char *id, const char *dict_str)
{
	total_tests++;

	Dictionary dict = dictionary_create_from_utf8(dict_str);

	// print_dictionary_data(dict);

	Parser parser(dict);
	parser.streamin("Hello");

	Lynk* ans =
	ALINK2(SET,
		ALINK3(LING,
			ANODE(LING_TYPE, "Wd"),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "LEFT-WALL"),
				ANODE(CONNECTOR, "Wd+")
			),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "Hello"),
				ANODE(CONNECTOR, "Wd-")
			)
		),
		ALINK3(LING,
			ANODE(LING_TYPE, "Wi"),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "LEFT-WALL"),
				ANODE(CONNECTOR, "Wi+")
			),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "Hello"),
				ANODE(CONNECTOR, "Wi-")
			)
		)
	);

	Lynk* output = parser.get_output_set();
	if (not (ans->operator==(output)))
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "=== Expecting:\n" << ans << endl;
		cout << "=== Got:\n" << output << endl;
		return false;
	}

	Lynk* final_state = parser.get_state();
	if (0 != final_state->get_arity())
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "Expecting the final state to be the empty set, but found:\n"
		     << final_state << endl;
		return false;
	}

	cout<<"PASS: test_alternative(" << id << ") " << endl;
	return true;
}

bool test_two_alts()
{
	return test_alternative("two alternatives",
		"LEFT-WALL: Wd+ or Wi+ or Wq+;"
		"Hello: Wd- or Wi-;"
	);
}

bool test_two_opts()
{
	return test_alternative("two alts plus opts",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: Wd- or Wi- or (Xj- & {A+ or B+});"
	);
}

bool test_two_one_opts()
{
	return test_alternative("two alt, or one opt",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: Wd- or {Wi-} or (Xj- & {A+ or B+});"
	);
}

bool test_two_all_opts()
{
	return test_alternative("two alts, or all opt",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: {Wd-} or {Wi-} or (Xj- & {A+ or B+});"
	);
}

bool test_two_and_opts()
{
	return test_alternative("two alts, and an opt",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: Wd- or (Wi- & {Xj- & {A+ or B+}} & {C+});"
	);
}

bool test_two_and_no_opts()
{
	return test_alternative("two alt, and all opt",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: Wd- or ({Wi-} & {Xj- & {A+ or B+}} & {C+});"
	);
}

bool test_two_and_excess()
{
	return test_alternative("two alt, and excess reqs",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: Wd- or (Wi- & Xj- & {A+ or B+} & {C+}) or Wi-;"
	);
}

int ntest_two()
{
	size_t num_failures = 0;

	if (!test_two_alts()) num_failures++;
	if (!test_two_opts()) num_failures++;
	if (!test_two_one_opts()) num_failures++;
	if (!test_two_all_opts()) num_failures++;
	if (!test_two_and_opts()) num_failures++;
	if (!test_two_and_no_opts()) num_failures++;
	if (!test_two_and_excess()) num_failures++;

	return num_failures;
}

// ==================================================================

bool test_simple_state(const char *id, const char *dict_str)
{
	total_tests++;

	Dictionary dict = dictionary_create_from_utf8(dict_str);

	// print_dictionary_data(dict);

	Parser parser(dict);
	// Expecting more words to follow, so a non-trivial state.
	parser.streamin("this");

	Lynk* output = parser.get_output_set();
	if (output)
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "Expecting no output, but found:\n"
		     << output << endl;
		return false;
	}

	Lynk* ans =
	ALINK1(SET,
		ALINK2(SEQ,
			ALINK2(WORD_CSET,
				ANODE(WORD, "this"),
				ANODE(CONNECTOR, "Ss*b+")
			),
			ALINK2(WORD_CSET,
				ANODE(WORD, "LEFT-WALL"),
				ALINK3(OR,
					ANODE(CONNECTOR, "Wd+"),
					ANODE(CONNECTOR, "Wi+"),
					ANODE(CONNECTOR, "Wq+")
				)
			)
		)
	);

	Lynk* state = parser.get_state();
	if (not (ans->operator==(state)))
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "=== Expecting state:\n" << ans << endl;
		cout << "=== Got state:\n" << state << endl;
		return false;
	}

	return true;
}

bool test_first_state()
{
	return test_simple_state("first state",
		"LEFT-WALL: Wd+ or Wi+ or Wq+;"
		"this: Ss*b+;"
	);
}

// ==================================================================

int
main(int argc, char *argv[])
{
	size_t num_failures = 0;

	num_failures += ntest_simple();
	num_failures += ntest_two();
	if (!test_first_state()) num_failures++;

	if (num_failures)
	{
		cout << "Test failures = " << num_failures
		     << " out of " << total_tests
		     << " total." << endl;
		exit(1);
	}

	cout << "All " << total_tests
		     << " tests pass." << endl;
	exit (0);
}

<commit_msg>Add new failing test<commit_after>/*************************************************************************/
/* Copyright (c) 2012                                                    */
/* Linas Vepstas <linasvepstas@gmail.com>                                */
/* All rights reserved                                                   */
/*                                                                       */
/*************************************************************************/

/// This file provides a unit test for the operation of the viterbi parser.

#include <stdlib.h>

#include <iostream>

#include <link-grammar/link-includes.h>
#include "read-dict.h"

#include "parser.h"

using namespace std;
using namespace link_grammar::viterbi;

#define Lynk link_grammar::viterbi::Link

#define ANODE(TYPE,NAME) (new Node(TYPE,NAME))
#define ALINK1(TYPE,A) (new Lynk(TYPE, A))
#define ALINK2(TYPE,A,B) (new Lynk(TYPE, A,B))
#define ALINK3(TYPE,A,B,C) (new Lynk(TYPE, A,B,C))

int total_tests = 0;

// ==================================================================
// A simple hello test; several different dictionaries
// should give exactly the same output.  The input sentence
// is just one word, it should connect to the left-wall in
// just one way.
bool test_hello(const char *id, const char *dict_str)
{
	total_tests++;

	Dictionary dict = dictionary_create_from_utf8(dict_str);

	// print_dictionary_data(dict);

	Parser parser(dict);
	parser.streamin("Hello");

	// This is the expected output, no matter what the
	// dictionary may be.
	Lynk* ans =
	ALINK1(SET,
		ALINK3(LING,
			ANODE(LING_TYPE, "Wd"),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "LEFT-WALL"),
				ANODE(CONNECTOR, "Wd+")
			),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "Hello"),
				ANODE(CONNECTOR, "Wd-")
			)
		)
	);

	Lynk* output = parser.get_output_set();
	if (not (ans->operator==(output)))
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "=== Expecting:\n" << ans << endl;
		cout << "=== Got:\n" << output << endl;
		return false;
	}

	Lynk* final_state = parser.get_state();
	if (0 != final_state->get_arity())
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "Expecting the final state to be the empty set, but found:\n"
		     << final_state << endl;
		return false;
	}

	cout<<"PASS: test_hello(" << id << ") " << endl;
	return true;
}

bool test_simplest()
{
	return test_hello ("test_simplest",
		"LEFT-WALL: Wd+;"
		"Hello: Wd-;"
	);
}

bool test_simple_left_disj()
{
	return test_hello ("simple left disj",
		"LEFT-WALL: Wd+ or Wi+ or Wq+;"
		"Hello: Wd-;"
	);
}

bool test_simple_optional_left_cset()
{
	return test_hello ("optional left cset",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {CP+} & {Xx+} & {RW+ or Xp+};"
		"Hello: Wd-;"
	);
}

bool test_simple_right_disj()
{
	return test_hello ("simple right disj",
		"LEFT-WALL: Wd+;"
		"Hello: Wd- or Wi-;"
	);
}

bool test_simple_optional()
{
	return test_hello ("optionals in both csets",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {CP+} & {Xx+} & {RW+ or Xp+};"
		"Hello: Wd- or Xi- or (Xj- & {A+ or B+});"
	);
}

bool test_simple_onereq()
{
	return test_hello ("one required link (simple)",
		"LEFT-WALL: Wd+ or Wi+ or Wq+;"
		"Hello: Wd- & {A+} & {B+} & {C+};"
	);
}

bool test_simple_zeroreq()
{
	return test_hello ("zero required links (simple)",
		"LEFT-WALL: Wd+ or Wi+ or Wq+;"
		"Hello: {Wd-} & {A+} & {B+} & {C+};"
	);
}

int ntest_simple()
{
	size_t num_failures = 0;

	if (!test_simplest()) num_failures++;
	if (!test_simple_left_disj()) num_failures++;
	if (!test_simple_optional_left_cset()) num_failures++;
	if (!test_simple_right_disj()) num_failures++;
	if (!test_simple_optional()) num_failures++;
	if (!test_simple_onereq()) num_failures++;
	if (!test_simple_zeroreq()) num_failures++;
	return num_failures;
}

// ==================================================================
// A test of two alternative parses of a sentence with single word in it.
// Expect to get back a set with two alternative parses, each parse is
// assigned a probability of 1/2.

bool test_alternative(const char *id, const char *dict_str)
{
	total_tests++;

	Dictionary dict = dictionary_create_from_utf8(dict_str);

	// print_dictionary_data(dict);

	Parser parser(dict);
	parser.streamin("Hello");

	Lynk* ans =
	ALINK2(SET,
		ALINK3(LING,
			ANODE(LING_TYPE, "Wd"),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "LEFT-WALL"),
				ANODE(CONNECTOR, "Wd+")
			),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "Hello"),
				ANODE(CONNECTOR, "Wd-")
			)
		),
		ALINK3(LING,
			ANODE(LING_TYPE, "Wi"),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "LEFT-WALL"),
				ANODE(CONNECTOR, "Wi+")
			),
			ALINK2(WORD_DISJ,
				ANODE(WORD, "Hello"),
				ANODE(CONNECTOR, "Wi-")
			)
		)
	);

	Lynk* output = parser.get_output_set();
	if (not (ans->operator==(output)))
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "=== Expecting:\n" << ans << endl;
		cout << "=== Got:\n" << output << endl;
		return false;
	}

	Lynk* final_state = parser.get_state();
	if (0 != final_state->get_arity())
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "Expecting the final state to be the empty set, but found:\n"
		     << final_state << endl;
		return false;
	}

	cout<<"PASS: test_alternative(" << id << ") " << endl;
	return true;
}

bool test_two_alts()
{
	return test_alternative("two alternatives",
		"LEFT-WALL: Wd+ or Wi+ or Wq+;"
		"Hello: Wd- or Wi-;"
	);
}

bool test_two_opts()
{
	return test_alternative("two alts plus opts",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: Wd- or Wi- or (Xj- & {A+ or B+});"
	);
}

bool test_two_one_opts()
{
	return test_alternative("two alt, or one opt",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: Wd- or {Wi-} or (Xj- & {A+ or B+});"
	);
}

bool test_two_all_opts()
{
	return test_alternative("two alts, or all opt",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: {Wd-} or {Wi-} or (Xj- & {A+ or B+});"
	);
}

bool test_two_and_opts()
{
	return test_alternative("two alts, and an opt",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: Wd- or (Wi- & {Xj- & {A+ or B+}} & {C+});"
	);
}

bool test_two_and_no_opts()
{
	return test_alternative("two alt, and all opt",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: Wd- or ({Wi-} & {Xj- & {A+ or B+}} & {C+});"
	);
}

bool test_two_and_excess()
{
	return test_alternative("two alt, and excess reqs",
		"LEFT-WALL: (Wd+ or Wi+ or Wq+) & {A+};"
		"Hello: Wd- or (Wi- & Xj- & {A+ or B+} & {C+}) or Wi-;"
	);
}

int ntest_two()
{
	size_t num_failures = 0;

	if (!test_two_alts()) num_failures++;
	if (!test_two_opts()) num_failures++;
	if (!test_two_one_opts()) num_failures++;
	if (!test_two_all_opts()) num_failures++;
	if (!test_two_and_opts()) num_failures++;
	if (!test_two_and_no_opts()) num_failures++;
	if (!test_two_and_excess()) num_failures++;

	return num_failures;
}

// ==================================================================

bool test_simple_state(const char *id, const char *dict_str)
{
	total_tests++;

	Dictionary dict = dictionary_create_from_utf8(dict_str);

	// print_dictionary_data(dict);

	Parser parser(dict);
	// Expecting more words to follow, so a non-trivial state.
	parser.streamin("this");

	Lynk* output = parser.get_output_set();
	if (output)
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "Expecting no output, but found:\n"
		     << output << endl;
		return false;
	}

	Lynk* ans =
	ALINK1(SET,
		ALINK2(SEQ,
			ALINK2(WORD_CSET,
				ANODE(WORD, "this"),
				ANODE(CONNECTOR, "Ss*b+")
			),
			ALINK2(WORD_CSET,
				ANODE(WORD, "LEFT-WALL"),
				ALINK3(OR,
					ANODE(CONNECTOR, "Wd+"),
					ANODE(CONNECTOR, "Wi+"),
					ANODE(CONNECTOR, "Wq+")
				)
			)
		)
	);

	Lynk* state = parser.get_state();
	if (not (ans->operator==(state)))
	{
		cout << "Error: test failure on test " << id << endl;
		cout << "=== Expecting state:\n" << ans << endl;
		cout << "=== Got state:\n" << state << endl;
		return false;
	}

	return true;
}

bool test_first_state()
{
	return test_simple_state("first state",
		"LEFT-WALL: Wd+ or Wi+ or Wq+;"
		"this: Ss*b+;"
	);
}

bool test_first_opt_lefty()
{
	return test_simple_state("first state, left-going optional",
		"LEFT-WALL: Wd+ or Wi+ or Wq+;"
		"this: Ss*b+ and {Xi-};"
	);
}

// ==================================================================

int
main(int argc, char *argv[])
{
	size_t num_failures = 0;

	num_failures += ntest_simple();
	num_failures += ntest_two();
	if (!test_first_state()) num_failures++;
	if (!test_first_opt_lefty()) num_failures++;

	if (num_failures)
	{
		cout << "Test failures = " << num_failures
		     << " out of " << total_tests
		     << " total." << endl;
		exit(1);
	}

	cout << "All " << total_tests
		     << " tests pass." << endl;
	exit (0);
}

<|endoftext|>


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

  Program:   Visualization Toolkit
  Module:    vtkQtChartSeriesOptions.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/
#ifdef _MSC_VER
// Disable warnings that Qt headers give.
#pragma warning(disable:4127)
#endif

#include "vtkQtChartSeriesOptions.h"

#include "vtkQtChartSeriesColors.h"

//----------------------------------------------------------------------------
vtkQtChartSeriesOptions::vtkQtChartSeriesOptions(QObject* parentObject)
  :QObject(parentObject)
{
  this->InitializeDefaults();
}

//----------------------------------------------------------------------------
vtkQtChartSeriesOptions::vtkQtChartSeriesOptions(
    const vtkQtChartSeriesOptions &other)
  : QObject(), Data(other.Data), Defaults(other.Defaults)
{
  this->InitializeDefaults();
}

//----------------------------------------------------------------------------
vtkQtChartSeriesOptions::~vtkQtChartSeriesOptions()
{
}

//----------------------------------------------------------------------------
vtkQtChartSeriesOptions &vtkQtChartSeriesOptions::operator=(
    const vtkQtChartSeriesOptions &other)
{
  this->Defaults = other.Defaults;
  this->Data = other.Data;
  return *this;
}

//----------------------------------------------------------------------------
vtkQtChartSeriesColors *vtkQtChartSeriesOptions::getSeriesColors() const
{
  return qobject_cast<vtkQtChartSeriesColors*>(
    this->getGenericOption(COLORS).value<QObject*>());
}

//----------------------------------------------------------------------------
void vtkQtChartSeriesOptions::setSeriesColors(vtkQtChartSeriesColors *colors)
{
  this->setGenericOption(COLORS, colors);
}

//----------------------------------------------------------------------------
void vtkQtChartSeriesOptions::setGenericOption(
  vtkQtChartSeriesOptions::OptionType type, const QVariant& value)
{
  QMap<OptionType, QVariant>::const_iterator iter = this->Data.find(type);
  if (iter == this->Data.end() || iter.value() != value)
    {
    // we call getGenericOption() since we need to take into consideration the
    // default value as well before firing the dataChanged() signal. This is
    // essential since the chart layers may do some non-idempotent operations
    // that can cause amazing issues when this signal is fired when no data has
    // really changed.
    QVariant oldValue = this->getGenericOption(type);
    this->Data[type] = value;
    if (oldValue != value)
      {
      emit this->dataChanged(type, value, oldValue);
      }
    }
}

//----------------------------------------------------------------------------
QVariant vtkQtChartSeriesOptions::getGenericOption(
  vtkQtChartSeriesOptions::OptionType type) const
{
  if (this->Data.contains(type))
    {
    return this->Data[type];
    }
  else if (this->Defaults.contains(type))
    {
    return this->Defaults[type];
    }

  return QVariant();
}

//----------------------------------------------------------------------------
void vtkQtChartSeriesOptions::setDefaultOption(
  OptionType type, const QVariant& value)
{
  QMap<OptionType, QVariant>::const_iterator iter = this->Defaults.find(type);
  if (iter == this->Defaults.end() || iter.value() != value)
    {
    QVariant oldValue = this->getGenericOption(type);
    this->Defaults[type] = value;
    if (this->getGenericOption(type) != oldValue)
      {
      emit this->dataChanged(type, value, oldValue);
      }
    }
}

//----------------------------------------------------------------------------
void vtkQtChartSeriesOptions::InitializeDefaults()
{
  this->Defaults[VISIBLE] = true;
  this->Defaults[PEN] = QPen(Qt::red);
  this->Defaults[BRUSH] = QBrush(Qt::red);
  this->Defaults[COLORS]= (vtkQtChartSeriesColors*)NULL;
  this->Defaults[AXES_CORNER] = vtkQtChartLayer::BottomLeft;
  this->Defaults[MARKER_STYLE] = vtkQtPointMarker::NoMarker;
  this->Defaults[MARKER_SIZE] = QSizeF(5, 5);
}

<commit_msg>COMP: fixed compiler error with Qt 4.5<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkQtChartSeriesOptions.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

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

=========================================================================*/
/*-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------*/
#ifdef _MSC_VER
// Disable warnings that Qt headers give.
#pragma warning(disable:4127)
#endif

#include "vtkQtChartSeriesOptions.h"

#include "vtkQtChartSeriesColors.h"

//----------------------------------------------------------------------------
vtkQtChartSeriesOptions::vtkQtChartSeriesOptions(QObject* parentObject)
  :QObject(parentObject)
{
  this->InitializeDefaults();
}

//----------------------------------------------------------------------------
vtkQtChartSeriesOptions::vtkQtChartSeriesOptions(
    const vtkQtChartSeriesOptions &other)
  : QObject(), Data(other.Data), Defaults(other.Defaults)
{
  this->InitializeDefaults();
}

//----------------------------------------------------------------------------
vtkQtChartSeriesOptions::~vtkQtChartSeriesOptions()
{
}

//----------------------------------------------------------------------------
vtkQtChartSeriesOptions &vtkQtChartSeriesOptions::operator=(
    const vtkQtChartSeriesOptions &other)
{
  this->Defaults = other.Defaults;
  this->Data = other.Data;
  return *this;
}

//----------------------------------------------------------------------------
vtkQtChartSeriesColors *vtkQtChartSeriesOptions::getSeriesColors() const
{
  return qobject_cast<vtkQtChartSeriesColors*>(
    this->getGenericOption(COLORS).value<QObject*>());
}

//----------------------------------------------------------------------------
void vtkQtChartSeriesOptions::setSeriesColors(vtkQtChartSeriesColors *colors)
{
  this->setGenericOption(COLORS, colors);
}

//----------------------------------------------------------------------------
void vtkQtChartSeriesOptions::setGenericOption(
  vtkQtChartSeriesOptions::OptionType type, const QVariant& value)
{
  QMap<OptionType, QVariant>::const_iterator iter = this->Data.find(type);
  if (iter == this->Data.end() || iter.value() != value)
    {
    // we call getGenericOption() since we need to take into consideration the
    // default value as well before firing the dataChanged() signal. This is
    // essential since the chart layers may do some non-idempotent operations
    // that can cause amazing issues when this signal is fired when no data has
    // really changed.
    QVariant oldValue = this->getGenericOption(type);
    this->Data[type] = value;
    if (oldValue != value)
      {
      emit this->dataChanged(type, value, oldValue);
      }
    }
}

//----------------------------------------------------------------------------
QVariant vtkQtChartSeriesOptions::getGenericOption(
  vtkQtChartSeriesOptions::OptionType type) const
{
  if (this->Data.contains(type))
    {
    return this->Data[type];
    }
  else if (this->Defaults.contains(type))
    {
    return this->Defaults[type];
    }

  return QVariant();
}

//----------------------------------------------------------------------------
void vtkQtChartSeriesOptions::setDefaultOption(
  OptionType type, const QVariant& value)
{
  QMap<OptionType, QVariant>::const_iterator iter = this->Defaults.find(type);
  if (iter == this->Defaults.end() || iter.value() != value)
    {
    QVariant oldValue = this->getGenericOption(type);
    this->Defaults[type] = value;
    if (this->getGenericOption(type) != oldValue)
      {
      emit this->dataChanged(type, value, oldValue);
      }
    }
}

//----------------------------------------------------------------------------
void vtkQtChartSeriesOptions::InitializeDefaults()
{
  this->Defaults[VISIBLE] = true;
  this->Defaults[PEN] = QPen(Qt::red);
  this->Defaults[BRUSH] = QBrush(Qt::red);
  this->Defaults[COLORS]= 0;
  this->Defaults[AXES_CORNER] = vtkQtChartLayer::BottomLeft;
  this->Defaults[MARKER_STYLE] = vtkQtPointMarker::NoMarker;
  this->Defaults[MARKER_SIZE] = QSizeF(5, 5);
}

<|endoftext|>


<commit_before>#pragma once
#include "meta/enable_if.hpp"
#include "range.hpp"
#include <algorithm>
#include <array>
#include <functional>

namespace frea {
	template <class MT>
	class Random {
		private:
			using MT_t = MT;
			MT_t	_mt;

			template <class T>
			using Lim = std::numeric_limits<T>;
			template <class T>
			struct Dist_Int {
				using uniform_t = std::uniform_int_distribution<T>;
				constexpr static Range<T> DefaultRange{Lim<T>::lowest(), Lim<T>::max()},
												NumericRange = DefaultRange;
			};
			template <class T>
			struct Dist_Float  {
				using uniform_t = std::uniform_real_distribution<T>;
				constexpr static Range<T> DefaultRange{T(0), T(1)},
												NumericRange{Lim<T>::lowest()/2, Lim<T>::max()/2};
			};
			template <class T, ENABLE_IF((std::is_integral<T>{}))>
			static Dist_Int<T> DetectDist();
			template <class T, ENABLE_IF((std::is_floating_point<T>{}))>
			static Dist_Float<T> DetectDist();
			template <class T>
			using Dist_t = decltype(DetectDist<T>());
		public:
			template <class T>
			class RObj {
				private:
					Random&			_rd;
					const Range<T>	_range;
				public:
					RObj(Random& rd, const Range<T>& r):
						_rd(rd),
						_range(r)
					{}
					RObj(const RObj&) = default;
					//! 実行時範囲指定
					auto operator ()(const Range<T>& r) const {
						return _rd.template getUniform<T>(r);
					}
					//! デフォルト範囲指定
					auto operator ()() const {
						return (*this)(_range);
					}
			};
		public:
			Random(MT_t mt) noexcept: _mt(std::move(mt)) {}
			Random(const Random&) = delete;
			Random(Random&& t) noexcept {
				*this = std::move(t);
			}
			Random& operator = (Random&& t) noexcept {
				swap(t);
				return *this;
			}
			void swap(Random& t) noexcept {
				std::swap(_mt, t._mt);
			}
			MT_t& refMt() noexcept {
				return _mt;
			}
			//! 一様分布
			/*! floating-pointの場合は0から1の乱数
				integerの場合は範囲指定なしnumeric_limits<T>::min() -> max()の乱数 */
			template <class T>
			T getUniform() {
				constexpr auto R = Dist_t<T>::DefaultRange;
				return getUniform<T>(R);
			}
			//! 一様分布
			/*! 数値として取り得る値の範囲 */
			template <class T>
			T getUniformNR() {
				constexpr auto R = Dist_t<T>::NumericRange;
				return getUniform<T>(R);
			}
			//! 指定範囲の一様分布(in range)
			template <class T>
			T getUniform(const Range<T>& range) {
				return typename Dist_t<T>::uniform_t(range.from, range.to)(_mt);
			}
			//! 一様分布を返すファンクタを作成
			template <class T>
			auto getUniformF(const Range<T>& r) noexcept {
				return RObj<T>(*this, r);
			}
			//! 一様分布を返すファンクタを作成
			template <class T>
			auto getUniformF() noexcept {
				constexpr auto R = Dist_t<T>::DefaultRange;
				return RObj<T>(*this, R);
			}
			//! 指定範囲の一様分布(vmax)
			template <class T>
			T getUniformMax(const T& vmax) {
				return getUniform<T>({Lim<T>::lowest(), vmax});
			}
			//! 指定範囲の一様分布(vmin)
			template <class T>
			T getUniformMin(const T& vmin) {
				return getUniform<T>({vmin, Lim<T>::max()});
			}

			template <std::size_t NumSeed>
			static Random<MT_t> Make() {
				std::random_device rnd;
				std::array<std::seed_seq::result_type, NumSeed> seed;
				std::generate(seed.begin(), seed.end(), std::ref(rnd));
				std::seed_seq seq(seed.begin(), seed.end());
				return std::move(Random<MT_t>(MT_t{seq}));
			}
	};
	using RandomMT = Random<std::mt19937>;
	using RandomMT64 = Random<std::mt19937_64>;
}
<commit_msg>Random: デフォルトの値範囲を1種類に固定<commit_after>#pragma once
#include "meta/enable_if.hpp"
#include "range.hpp"
#include <algorithm>
#include <array>
#include <functional>

namespace frea {
	template <class MT>
	class Random {
		private:
			using MT_t = MT;
			MT_t	_mt;

			template <class T>
			using Lim = std::numeric_limits<T>;
			template <class T>
			struct Dist_Int {
				using uniform_t = std::uniform_int_distribution<T>;
				constexpr static Range<T> NumericRange{Lim<T>::lowest(), Lim<T>::max()};
			};
			template <class T>
			struct Dist_Float  {
				using uniform_t = std::uniform_real_distribution<T>;
				constexpr static Range<T> NumericRange{Lim<T>::lowest()/2, Lim<T>::max()/2};
			};
			template <class T, ENABLE_IF((std::is_integral<T>{}))>
			static Dist_Int<T> DetectDist();
			template <class T, ENABLE_IF((std::is_floating_point<T>{}))>
			static Dist_Float<T> DetectDist();
			template <class T>
			using Dist_t = decltype(DetectDist<T>());
		public:
			template <class T>
			class RObj {
				private:
					Random&			_rd;
					const Range<T>	_range;
				public:
					RObj(Random& rd, const Range<T>& r):
						_rd(rd),
						_range(r)
					{}
					RObj(const RObj&) = default;
					//! 実行時範囲指定
					auto operator ()(const Range<T>& r) const {
						return _rd.template getUniform<T>(r);
					}
					//! デフォルト範囲指定
					auto operator ()() const {
						return (*this)(_range);
					}
			};
		public:
			Random(MT_t mt) noexcept: _mt(std::move(mt)) {}
			Random(const Random&) = delete;
			Random(Random&& t) noexcept {
				*this = std::move(t);
			}
			Random& operator = (Random&& t) noexcept {
				swap(t);
				return *this;
			}
			void swap(Random& t) noexcept {
				std::swap(_mt, t._mt);
			}
			MT_t& refMt() noexcept {
				return _mt;
			}
			//! 一様分布
			/*! 範囲がnumeric_limits<T>::lowest() -> max()の乱数 */
			template <class T>
			T getUniform() {
				constexpr auto R = Dist_t<T>::NumericRange;
				return getUniform<T>(R);
			}
			//! 指定範囲の一様分布(in range)
			template <class T>
			T getUniform(const Range<T>& range) {
				return typename Dist_t<T>::uniform_t(range.from, range.to)(_mt);
			}
			//! 一様分布を返すファンクタを作成
			template <class T>
			auto getUniformF(const Range<T>& r) noexcept {
				return RObj<T>(*this, r);
			}
			//! 一様分布を返すファンクタを作成
			template <class T>
			auto getUniformF() noexcept {
				constexpr auto R = Dist_t<T>::NumericRange;
				return RObj<T>(*this, R);
			}
			//! 指定範囲の一様分布(vmax)
			template <class T>
			T getUniformMax(const T& vmax) {
				return getUniform<T>({Lim<T>::lowest(), vmax});
			}
			//! 指定範囲の一様分布(vmin)
			template <class T>
			T getUniformMin(const T& vmin) {
				return getUniform<T>({vmin, Lim<T>::max()});
			}

			template <std::size_t NumSeed>
			static Random<MT_t> Make() {
				std::random_device rnd;
				std::array<std::seed_seq::result_type, NumSeed> seed;
				std::generate(seed.begin(), seed.end(), std::ref(rnd));
				std::seed_seq seq(seed.begin(), seed.end());
				return std::move(Random<MT_t>(MT_t{seq}));
			}
	};
	using RandomMT = Random<std::mt19937>;
	using RandomMT64 = Random<std::mt19937_64>;
}
<|endoftext|>


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

#include "ViewCSSImp.h"

#include <org/w3c/dom/Text.h>
#include <org/w3c/dom/Comment.h>

#include <new>
#include <boost/bind.hpp>

#include "CSSStyleRuleImp.h"
#include "CSSStyleDeclarationImp.h"
#include "CSSStyleSheetImp.h"
#include "DocumentImp.h"

#include "Box.h"
#include "StackingContext.h"

#include "Test.util.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

namespace {

bool isReplacedElement(Element& element)
{
    std::u16string tag = element.getLocalName();  // TODO: Check HTML namespace
    if (tag == u"img" || tag == u"iframe" || tag == u"video")  // TODO: more tags to come...
        return true;
    return false;
}

}

ViewCSSImp::ViewCSSImp(DocumentWindowPtr window, css::CSSStyleSheet defaultStyleSheet) :
    window(window),
    defaultStyleSheet(defaultStyleSheet),
    stackingContexts(0),
    hovered(0),
    dpi(96),
    mutationListener(boost::bind(&ViewCSSImp::handleMutation, this, _1))
{
    setMediumFontSize(16);
    getDocument().addEventListener(u"DOMAttrModified", &mutationListener);
}

ViewCSSImp::~ViewCSSImp()
{
    getDocument().removeEventListener(u"DOMAttrModified", &mutationListener);
}

Box* ViewCSSImp::boxFromPoint(int x, int y)
{
    if (!boxTree)
        return 0;
    if (Box* target = boxTree.get()->boxFromPoint(x, y))
        return target;
    return boxTree.get();
}

bool ViewCSSImp::isHovered(Node node)
{
    for (Node i = hovered; i; i = i.getParentNode()) {
        if (node == i)
            return true;
    }
    return false;
}

void ViewCSSImp::handleMutation(events::Event event)
{
    if (boxTree)
        boxTree->setFlags(1);
}

void ViewCSSImp::findDeclarations(DeclarationSet& set, Element element, css::CSSRuleList list)
{
    if (!list)
        return;
    unsigned int size = list.getLength();
    for (unsigned int i = 0; i < size; ++i) {
        css::CSSRule rule = list.getElement(i);
        if (CSSStyleRuleImp* imp = dynamic_cast<CSSStyleRuleImp*>(rule.self())) {
            CSSSelector* selector = imp->match(element, this);
            if (!selector)
                continue;
            unsigned pseudoElementID = 0;
            if (CSSPseudoElementSelector* pseudo = selector->getPseudoElement())
                pseudoElementID = pseudo->getID();
            PrioritizedDeclaration decl(imp->getLastSpecificity(), dynamic_cast<CSSStyleDeclarationImp*>(imp->getStyle().self()), pseudoElementID);
            set.insert(decl);
        }
    }
}

void ViewCSSImp::render()
{
    if (boxTree)
        boxTree->render(this);
}

void ViewCSSImp::cascade()
{
    map.clear();
    delete stackingContexts;
    stackingContexts = 0;
    cascade(getDocument(), 0);

    printComputedValues(getDocument(), this);  // for debug
}

void ViewCSSImp::cascade(Node node, CSSStyleDeclarationImp* parentStyle)
{
    CSSStyleDeclarationImp* style = 0;
    if (node.getNodeType() == Node::ELEMENT_NODE) {
        Element element = interface_cast<Element>(node);

        style = new(std::nothrow) CSSStyleDeclarationImp;
        if (!style) {
            map.erase(element);
            return;  // TODO: error
        }
        map[element] = style;
        DeclarationSet set;
        findDeclarations(set, element, defaultStyleSheet.getCssRules());
        for (auto i = set.begin(); i != set.end(); ++i) {
            if (CSSStyleDeclarationImp* pseudo = style->createPseudoElementStyle((*i).pseudoElementID))
                pseudo->specify((*i).decl);
        }
        set.clear();

        stylesheets::StyleSheetList styleSheets = element.getOwnerDocument().getStyleSheets();
        for (unsigned i = 0; i < styleSheets.getLength(); ++i) {
            stylesheets::StyleSheet sheet = styleSheets.getElement(i);
            if (CSSStyleSheetImp* imp = dynamic_cast<CSSStyleSheetImp*>(sheet.self()))
                findDeclarations(set, element, imp->getCssRules());
        }
        for (auto i = set.begin(); i != set.end(); ++i) {
            if (CSSStyleDeclarationImp* pseudo = style->createPseudoElementStyle((*i).pseudoElementID))
                pseudo->specify((*i).decl);
        }
        for (auto i = set.begin(); i != set.end(); ++i) {
            if (CSSStyleDeclarationImp* pseudo = style->createPseudoElementStyle((*i).pseudoElementID))
                pseudo->specifyImportant((*i).decl);
        }
        set.clear();

        // TODO: process user normal declarations and user important declarations

        if (html::HTMLElement htmlElement = interface_cast<html::HTMLElement>(element)) {  // TODO: type check
            if (css::CSSStyleDeclaration decl = htmlElement.getStyle())
                style->specify(static_cast<CSSStyleDeclarationImp*>(decl.self()));
        }

        style->compute(this, parentStyle, element);
    }
    for (Node child = node.getFirstChild(); child; child = child.getNextSibling())
        cascade(child, style);
}

// In this step, neither inline-level boxes nor line boxes are generated.
// Those will be generated later by layOut().
BlockLevelBox* ViewCSSImp::layOutBlockBoxes(Node node, BlockLevelBox* parentBox, BlockLevelBox* siblingBox, CSSStyleDeclarationImp* style)
{
    BlockLevelBox* newBox = 0;
    switch (node.getNodeType()) {
    case Node::TEXT_NODE:
        newBox = layOutBlockBoxes(interface_cast<Text>(node), parentBox, siblingBox, style);
        break;
    case Node::ELEMENT_NODE:
        newBox = layOutBlockBoxes(interface_cast<Element>(node), parentBox, siblingBox, style);
        break;
    case Node::DOCUMENT_NODE:
        // Iterate over from back to front to process run-in boxes
        for (Node child = node.getLastChild(); child; child = child.getPreviousSibling()) {
            if (BlockLevelBox* box = layOutBlockBoxes(child, parentBox, newBox, style))
                newBox = box;
        }
        break;
    default:
        break;
    }
    return newBox;
}

BlockLevelBox* ViewCSSImp::layOutBlockBoxes(Text text, BlockLevelBox* parentBox, BlockLevelBox* siblingBox, CSSStyleDeclarationImp* style)
{
    if (!parentBox || !style)
        return 0;
    if (!parentBox->hasChildBoxes()) {
        parentBox->insertInline(text);
        return 0;
    }
    if (!parentBox->hasAnonymousBox()) {
        // cf. http://www.w3.org/TR/CSS2/visuren.html#anonymous
        // White space content that would subsequently be collapsed
        // away according to the 'white-space' property does not
        // generate any anonymous inline boxes.
        std::u16string data;
        bool whiteSpace = true;
        switch (style->whiteSpace.getValue()) {
        case CSSWhiteSpaceValueImp::Normal:
        case CSSWhiteSpaceValueImp::Nowrap:
        case CSSWhiteSpaceValueImp::PreLine:
            data = text.getData();  // TODO: make this faster
            for (auto i = data.begin(); i != data.end(); ++i) {
                if (!isSpace(*i)) {
                    whiteSpace = false;
                    break;
                }
            }
            if (whiteSpace)
                return 0;
            break;
        }
    }
    if (BlockLevelBox* anonymousBox = parentBox->getAnonymousBox()) {
        anonymousBox->insertInline(text);
        return anonymousBox;
    }
    return 0;
}

BlockLevelBox* ViewCSSImp::layOutBlockBoxes(Element element, BlockLevelBox* parentBox, BlockLevelBox* siblingBox, CSSStyleDeclarationImp* style, bool asBlock)
{
    style = map[element].get();
    if (!style || style->display.isNone())
        return 0;
    bool runIn = style->display.isRunIn();
    BlockLevelBox* currentBox = parentBox;
    BlockLevelBox* childBox = 0;
    if (style->isFloat() || style->isAbsolutelyPositioned()) {
        currentBox = new(std::nothrow) BlockLevelBox(element, style);
        if (!currentBox)
            return 0;  // TODO: error
        if (!currentBox->establishFormattingContext())
            return 0;  // TODO: error
        style->addBox(currentBox);
        // Do not insert currentBox into parentBox
    } else if (style->isBlockLevel() || runIn || asBlock) {
        // Create a temporary block-level box for the run-in box, too.
        if (parentBox && parentBox->hasInline()) {
            if (!parentBox->getAnonymousBox())
                return 0;
            assert(!parentBox->hasInline());
        }
        currentBox = new(std::nothrow) BlockLevelBox(element, style);
        if (!currentBox)
            return 0;
        style->addBox(currentBox);
        if (parentBox) {
            if (Box* first = parentBox->getFirstChild())
                parentBox->insertBefore(currentBox, first);
            else
                parentBox->appendChild(currentBox);
        } else
            runIn = false;

        // Establish a new formatting context?
        if (!parentBox || style->isFlowRoot()) {
            if (!currentBox->establishFormattingContext())
                return 0;  // TODO error
        }
    } else if (style->isInlineBlock() || isReplacedElement(element)) {
        assert(currentBox);
        if (!currentBox->hasChildBoxes())
            currentBox->insertInline(element);
        else if (BlockLevelBox* anonymousBox = currentBox->getAnonymousBox()) {
            anonymousBox->insertInline(element);
            return anonymousBox;
        }
        return currentBox;
    }

    if (CSSStyleDeclarationImp* afterStyle = style->getPseudoElementStyle(CSSPseudoElementSelector::After)) {
        afterStyle->compute(this, style, element);
        if (Element after = afterStyle->content.eval(getDocument(), element)) {
            map[after] = afterStyle;
            if (BlockLevelBox* box = layOutBlockBoxes(after, currentBox, childBox, style))
                childBox = box;
        }
    }

    // Iterate over from back to front to process run-in boxes
    for (Node child = element.getLastChild(); child; child = child.getPreviousSibling()) {
        if (BlockLevelBox* box = layOutBlockBoxes(child, currentBox, childBox, style))
            childBox = box;
    }

    if (runIn && !currentBox->hasChildBoxes() && siblingBox) {
        assert(siblingBox->getBoxType() == Box::BLOCK_LEVEL_BOX);
        siblingBox->spliceInline(currentBox);
        parentBox->removeChild(currentBox);
        delete currentBox;
        currentBox = 0;
    }

    if (CSSStyleDeclarationImp* beforeStyle = style->getPseudoElementStyle(CSSPseudoElementSelector::Before)) {
        beforeStyle->compute(this, style, element);
        if (Element before = beforeStyle->content.eval(getDocument(), element)) {
            map[before] = beforeStyle;
            if (BlockLevelBox* box = layOutBlockBoxes(before, currentBox, childBox, style))
                childBox = box;
        }
    }

    if (!currentBox)
        currentBox = childBox;
    else if (currentBox == parentBox)
        currentBox = 0;
    else if (currentBox->isFloat() || currentBox->isAbsolutelyPositioned()) {
        floatMap[element] = currentBox;
        if (parentBox) {
            if (!parentBox->hasChildBoxes())
                parentBox->insertInline(element);
            else if (BlockLevelBox* anonymousBox = parentBox->getAnonymousBox()) {
                anonymousBox->insertInline(element);
                return anonymousBox;
            }
        }
    }
    return currentBox;
}

// Lay out a tree box block-level boxes
BlockLevelBox* ViewCSSImp::layOutBlockBoxes()
{
    floatMap.clear();
    boxTree = layOutBlockBoxes(getDocument(), 0, 0, 0);
    return boxTree.get();
}

BlockLevelBox* ViewCSSImp::layOut()
{
    layOutBlockBoxes();
    if (!boxTree)
        return 0;
    // Expand line boxes and inline-level boxes in each block-level box
    boxTree->layOut(this, 0);

    // Lay out absolute boxes.
    // Since absolute boxes could be created by layOutAbsolute() itself,
    // we cannot simply iterate over floatMap.
    // TODO: refine the code
    std::map<Node, BlockLevelBoxPtr> tmp;
    while (!floatMap.empty()) {
        auto i = floatMap.begin();
        BlockLevelBoxPtr box = i->second;
        if (box->isAbsolutelyPositioned())
            box->layOutAbsolute(this, i->first);
        tmp.insert(*i);
        floatMap.erase(i);
    }
    floatMap.swap(tmp);
    if (stackingContexts) {
        stackingContexts->eval();
        stackingContexts->dump();
    }
    return boxTree.get();
}

BlockLevelBox* ViewCSSImp::dump()
{
    boxTree->dump(this);
    return boxTree.get();
}

CSSStyleDeclarationImp* ViewCSSImp::getStyle(Element elt, Nullable<std::u16string> pseudoElt)
{
    auto i = map.find(elt);
    if (i == map.end())
        return 0;
    CSSStyleDeclarationImp* style = i->second.get();
    if (!pseudoElt.hasValue() || pseudoElt.value().length() == 0)
        return style;
    return style->getPseudoElementStyle(pseudoElt.value());
}

// ViewCSS
css::CSSStyleDeclaration ViewCSSImp::getComputedStyle(Element elt, Nullable<std::u16string> pseudoElt) {
    return getStyle(elt, pseudoElt);
}

}}}}  // org::w3c::dom::bootstrap
<commit_msg>(ViewCSSImp::layOutBlockBoxes) : Fix to process the run-in box after placing the pseudo-elements.<commit_after>/*
 * Copyright 2010, 2011 Esrille Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ViewCSSImp.h"

#include <org/w3c/dom/Text.h>
#include <org/w3c/dom/Comment.h>

#include <new>
#include <boost/bind.hpp>

#include "CSSStyleRuleImp.h"
#include "CSSStyleDeclarationImp.h"
#include "CSSStyleSheetImp.h"
#include "DocumentImp.h"

#include "Box.h"
#include "StackingContext.h"

#include "Test.util.h"

namespace org { namespace w3c { namespace dom { namespace bootstrap {

namespace {

bool isReplacedElement(Element& element)
{
    std::u16string tag = element.getLocalName();  // TODO: Check HTML namespace
    if (tag == u"img" || tag == u"iframe" || tag == u"video")  // TODO: more tags to come...
        return true;
    return false;
}

}

ViewCSSImp::ViewCSSImp(DocumentWindowPtr window, css::CSSStyleSheet defaultStyleSheet) :
    window(window),
    defaultStyleSheet(defaultStyleSheet),
    stackingContexts(0),
    hovered(0),
    dpi(96),
    mutationListener(boost::bind(&ViewCSSImp::handleMutation, this, _1))
{
    setMediumFontSize(16);
    getDocument().addEventListener(u"DOMAttrModified", &mutationListener);
}

ViewCSSImp::~ViewCSSImp()
{
    getDocument().removeEventListener(u"DOMAttrModified", &mutationListener);
}

Box* ViewCSSImp::boxFromPoint(int x, int y)
{
    if (!boxTree)
        return 0;
    if (Box* target = boxTree.get()->boxFromPoint(x, y))
        return target;
    return boxTree.get();
}

bool ViewCSSImp::isHovered(Node node)
{
    for (Node i = hovered; i; i = i.getParentNode()) {
        if (node == i)
            return true;
    }
    return false;
}

void ViewCSSImp::handleMutation(events::Event event)
{
    if (boxTree)
        boxTree->setFlags(1);
}

void ViewCSSImp::findDeclarations(DeclarationSet& set, Element element, css::CSSRuleList list)
{
    if (!list)
        return;
    unsigned int size = list.getLength();
    for (unsigned int i = 0; i < size; ++i) {
        css::CSSRule rule = list.getElement(i);
        if (CSSStyleRuleImp* imp = dynamic_cast<CSSStyleRuleImp*>(rule.self())) {
            CSSSelector* selector = imp->match(element, this);
            if (!selector)
                continue;
            unsigned pseudoElementID = 0;
            if (CSSPseudoElementSelector* pseudo = selector->getPseudoElement())
                pseudoElementID = pseudo->getID();
            PrioritizedDeclaration decl(imp->getLastSpecificity(), dynamic_cast<CSSStyleDeclarationImp*>(imp->getStyle().self()), pseudoElementID);
            set.insert(decl);
        }
    }
}

void ViewCSSImp::render()
{
    if (boxTree)
        boxTree->render(this);
}

void ViewCSSImp::cascade()
{
    map.clear();
    delete stackingContexts;
    stackingContexts = 0;
    cascade(getDocument(), 0);

    printComputedValues(getDocument(), this);  // for debug
}

void ViewCSSImp::cascade(Node node, CSSStyleDeclarationImp* parentStyle)
{
    CSSStyleDeclarationImp* style = 0;
    if (node.getNodeType() == Node::ELEMENT_NODE) {
        Element element = interface_cast<Element>(node);

        style = new(std::nothrow) CSSStyleDeclarationImp;
        if (!style) {
            map.erase(element);
            return;  // TODO: error
        }
        map[element] = style;
        DeclarationSet set;
        findDeclarations(set, element, defaultStyleSheet.getCssRules());
        for (auto i = set.begin(); i != set.end(); ++i) {
            if (CSSStyleDeclarationImp* pseudo = style->createPseudoElementStyle((*i).pseudoElementID))
                pseudo->specify((*i).decl);
        }
        set.clear();

        stylesheets::StyleSheetList styleSheets = element.getOwnerDocument().getStyleSheets();
        for (unsigned i = 0; i < styleSheets.getLength(); ++i) {
            stylesheets::StyleSheet sheet = styleSheets.getElement(i);
            if (CSSStyleSheetImp* imp = dynamic_cast<CSSStyleSheetImp*>(sheet.self()))
                findDeclarations(set, element, imp->getCssRules());
        }
        for (auto i = set.begin(); i != set.end(); ++i) {
            if (CSSStyleDeclarationImp* pseudo = style->createPseudoElementStyle((*i).pseudoElementID))
                pseudo->specify((*i).decl);
        }
        for (auto i = set.begin(); i != set.end(); ++i) {
            if (CSSStyleDeclarationImp* pseudo = style->createPseudoElementStyle((*i).pseudoElementID))
                pseudo->specifyImportant((*i).decl);
        }
        set.clear();

        // TODO: process user normal declarations and user important declarations

        if (html::HTMLElement htmlElement = interface_cast<html::HTMLElement>(element)) {  // TODO: type check
            if (css::CSSStyleDeclaration decl = htmlElement.getStyle())
                style->specify(static_cast<CSSStyleDeclarationImp*>(decl.self()));
        }

        style->compute(this, parentStyle, element);
    }
    for (Node child = node.getFirstChild(); child; child = child.getNextSibling())
        cascade(child, style);
}

// In this step, neither inline-level boxes nor line boxes are generated.
// Those will be generated later by layOut().
BlockLevelBox* ViewCSSImp::layOutBlockBoxes(Node node, BlockLevelBox* parentBox, BlockLevelBox* siblingBox, CSSStyleDeclarationImp* style)
{
    BlockLevelBox* newBox = 0;
    switch (node.getNodeType()) {
    case Node::TEXT_NODE:
        newBox = layOutBlockBoxes(interface_cast<Text>(node), parentBox, siblingBox, style);
        break;
    case Node::ELEMENT_NODE:
        newBox = layOutBlockBoxes(interface_cast<Element>(node), parentBox, siblingBox, style);
        break;
    case Node::DOCUMENT_NODE:
        // Iterate over from back to front to process run-in boxes
        for (Node child = node.getLastChild(); child; child = child.getPreviousSibling()) {
            if (BlockLevelBox* box = layOutBlockBoxes(child, parentBox, newBox, style))
                newBox = box;
        }
        break;
    default:
        break;
    }
    return newBox;
}

BlockLevelBox* ViewCSSImp::layOutBlockBoxes(Text text, BlockLevelBox* parentBox, BlockLevelBox* siblingBox, CSSStyleDeclarationImp* style)
{
    if (!parentBox || !style)
        return 0;
    if (!parentBox->hasChildBoxes()) {
        parentBox->insertInline(text);
        return 0;
    }
    if (!parentBox->hasAnonymousBox()) {
        // cf. http://www.w3.org/TR/CSS2/visuren.html#anonymous
        // White space content that would subsequently be collapsed
        // away according to the 'white-space' property does not
        // generate any anonymous inline boxes.
        std::u16string data;
        bool whiteSpace = true;
        switch (style->whiteSpace.getValue()) {
        case CSSWhiteSpaceValueImp::Normal:
        case CSSWhiteSpaceValueImp::Nowrap:
        case CSSWhiteSpaceValueImp::PreLine:
            data = text.getData();  // TODO: make this faster
            for (auto i = data.begin(); i != data.end(); ++i) {
                if (!isSpace(*i)) {
                    whiteSpace = false;
                    break;
                }
            }
            if (whiteSpace)
                return 0;
            break;
        }
    }
    if (BlockLevelBox* anonymousBox = parentBox->getAnonymousBox()) {
        anonymousBox->insertInline(text);
        return anonymousBox;
    }
    return 0;
}

BlockLevelBox* ViewCSSImp::layOutBlockBoxes(Element element, BlockLevelBox* parentBox, BlockLevelBox* siblingBox, CSSStyleDeclarationImp* style, bool asBlock)
{
    style = map[element].get();
    if (!style || style->display.isNone())
        return 0;
    bool runIn = style->display.isRunIn();
    BlockLevelBox* currentBox = parentBox;
    BlockLevelBox* childBox = 0;
    if (style->isFloat() || style->isAbsolutelyPositioned()) {
        currentBox = new(std::nothrow) BlockLevelBox(element, style);
        if (!currentBox)
            return 0;  // TODO: error
        if (!currentBox->establishFormattingContext())
            return 0;  // TODO: error
        style->addBox(currentBox);
        // Do not insert currentBox into parentBox
    } else if (style->isBlockLevel() || runIn || asBlock) {
        // Create a temporary block-level box for the run-in box, too.
        if (parentBox && parentBox->hasInline()) {
            if (!parentBox->getAnonymousBox())
                return 0;
            assert(!parentBox->hasInline());
        }
        currentBox = new(std::nothrow) BlockLevelBox(element, style);
        if (!currentBox)
            return 0;
        style->addBox(currentBox);
        if (parentBox) {
            if (Box* first = parentBox->getFirstChild())
                parentBox->insertBefore(currentBox, first);
            else
                parentBox->appendChild(currentBox);
        } else
            runIn = false;

        // Establish a new formatting context?
        if (!parentBox || style->isFlowRoot()) {
            if (!currentBox->establishFormattingContext())
                return 0;  // TODO error
        }
    } else if (style->isInlineBlock() || isReplacedElement(element)) {
        assert(currentBox);
        if (!currentBox->hasChildBoxes())
            currentBox->insertInline(element);
        else if (BlockLevelBox* anonymousBox = currentBox->getAnonymousBox()) {
            anonymousBox->insertInline(element);
            return anonymousBox;
        }
        return currentBox;
    }

    if (CSSStyleDeclarationImp* afterStyle = style->getPseudoElementStyle(CSSPseudoElementSelector::After)) {
        afterStyle->compute(this, style, element);
        if (Element after = afterStyle->content.eval(getDocument(), element)) {
            map[after] = afterStyle;
            if (BlockLevelBox* box = layOutBlockBoxes(after, currentBox, childBox, style))
                childBox = box;
        }
    }

    // Iterate over from back to front to process run-in boxes
    for (Node child = element.getLastChild(); child; child = child.getPreviousSibling()) {
        if (BlockLevelBox* box = layOutBlockBoxes(child, currentBox, childBox, style))
            childBox = box;
    }

    if (CSSStyleDeclarationImp* beforeStyle = style->getPseudoElementStyle(CSSPseudoElementSelector::Before)) {
        beforeStyle->compute(this, style, element);
        if (Element before = beforeStyle->content.eval(getDocument(), element)) {
            map[before] = beforeStyle;
            if (BlockLevelBox* box = layOutBlockBoxes(before, currentBox, childBox, style))
                childBox = box;
        }
    }

    // cf. http://www.w3.org/TR/2010/WD-CSS2-20101207/generate.html#before-after-content
    if (runIn && !currentBox->hasChildBoxes() && siblingBox) {
        assert(siblingBox->getBoxType() == Box::BLOCK_LEVEL_BOX);
        siblingBox->spliceInline(currentBox);
        parentBox->removeChild(currentBox);
        delete currentBox;
        currentBox = 0;
    }

    if (!currentBox)
        currentBox = childBox;
    else if (currentBox == parentBox)
        currentBox = 0;
    else if (currentBox->isFloat() || currentBox->isAbsolutelyPositioned()) {
        floatMap[element] = currentBox;
        if (parentBox) {
            if (!parentBox->hasChildBoxes())
                parentBox->insertInline(element);
            else if (BlockLevelBox* anonymousBox = parentBox->getAnonymousBox()) {
                anonymousBox->insertInline(element);
                return anonymousBox;
            }
        }
    }
    return currentBox;
}

// Lay out a tree box block-level boxes
BlockLevelBox* ViewCSSImp::layOutBlockBoxes()
{
    floatMap.clear();
    boxTree = layOutBlockBoxes(getDocument(), 0, 0, 0);
    return boxTree.get();
}

BlockLevelBox* ViewCSSImp::layOut()
{
    layOutBlockBoxes();
    if (!boxTree)
        return 0;
    // Expand line boxes and inline-level boxes in each block-level box
    boxTree->layOut(this, 0);

    // Lay out absolute boxes.
    // Since absolute boxes could be created by layOutAbsolute() itself,
    // we cannot simply iterate over floatMap.
    // TODO: refine the code
    std::map<Node, BlockLevelBoxPtr> tmp;
    while (!floatMap.empty()) {
        auto i = floatMap.begin();
        BlockLevelBoxPtr box = i->second;
        if (box->isAbsolutelyPositioned())
            box->layOutAbsolute(this, i->first);
        tmp.insert(*i);
        floatMap.erase(i);
    }
    floatMap.swap(tmp);
    if (stackingContexts) {
        stackingContexts->eval();
        stackingContexts->dump();
    }
    return boxTree.get();
}

BlockLevelBox* ViewCSSImp::dump()
{
    boxTree->dump(this);
    return boxTree.get();
}

CSSStyleDeclarationImp* ViewCSSImp::getStyle(Element elt, Nullable<std::u16string> pseudoElt)
{
    auto i = map.find(elt);
    if (i == map.end())
        return 0;
    CSSStyleDeclarationImp* style = i->second.get();
    if (!pseudoElt.hasValue() || pseudoElt.value().length() == 0)
        return style;
    return style->getPseudoElementStyle(pseudoElt.value());
}

// ViewCSS
css::CSSStyleDeclaration ViewCSSImp::getComputedStyle(Element elt, Nullable<std::u16string> pseudoElt) {
    return getStyle(elt, pseudoElt);
}

}}}}  // org::w3c::dom::bootstrap
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <ocidl.h>
#include <commdlg.h>

#include <string>

#include "base/scoped_ptr.h"
#include "printing/printing_test.h"
#include "printing/printing_context.h"
#include "printing/printing_context_win.h"
#include "printing/print_settings.h"
#include "testing/gtest/include/gtest/gtest.h"

// This test is automatically disabled if no printer is available.
class PrintingContextTest : public PrintingTest<testing::Test> {
 public:
  void PrintSettingsCallback(printing::PrintingContext::Result result) {
    result_ = result;
  }

 protected:
  printing::PrintingContext::Result result() const { return result_; }

 private:
  printing::PrintingContext::Result result_;
};

// This is a fake PrintDlgEx implementation that sets the right fields in
// |lppd| to trigger a bug in older revisions of PrintingContext.
HRESULT WINAPI PrintDlgExMock(LPPRINTDLGEX lppd) {
  // The interesting bits:
  // Pretend the user hit print
  lppd->dwResultAction = PD_RESULT_PRINT;

  // Pretend the page range is 1-5, but since lppd->Flags does not have
  // PD_SELECTION set, this really shouldn't matter.
  lppd->nPageRanges = 1;
  lppd->lpPageRanges = new PRINTPAGERANGE[1];
  lppd->lpPageRanges[0].nFromPage = 1;
  lppd->lpPageRanges[0].nToPage = 5;

  // Painful paperwork.
  std::wstring printer_name = PrintingContextTest::GetDefaultPrinter();
  HANDLE printer;
  if (!OpenPrinter(const_cast<wchar_t*>(printer_name.c_str()), &printer, NULL))
    return E_FAIL;

  scoped_array<uint8> buffer;
  DEVMODE* dev_mode = NULL;
  PRINTER_INFO_2* info_2 = NULL;

  printing::PrintingContextWin::GetPrinterHelper(printer, 2, &buffer);
  if (buffer.get()) {
    info_2 = reinterpret_cast<PRINTER_INFO_2*>(buffer.get());
    if (info_2->pDevMode != NULL)
      dev_mode = info_2->pDevMode;
  }
  if (!dev_mode)
    return E_FAIL;

  if (!printing::PrintingContextWin::AllocateContext(printer_name, dev_mode,
      &lppd->hDC)) {
    return E_FAIL;
  }

  size_t dev_mode_size = dev_mode->dmSize + dev_mode->dmDriverExtra;
  lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, dev_mode_size);
  if (!lppd->hDevMode)
    return E_FAIL;
  void* dev_mode_ptr = GlobalLock(lppd->hDevMode);
  if (!dev_mode_ptr)
    return E_FAIL;
  memcpy(dev_mode_ptr, dev_mode, dev_mode_size);
  GlobalUnlock(lppd->hDevMode);

  size_t driver_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pDriverName);
  size_t printer_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pPrinterName);
  size_t port_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pPortName);
  size_t dev_names_size = sizeof(DEVNAMES) + driver_size + printer_size +
      port_size;
  lppd->hDevNames = GlobalAlloc(GHND, dev_names_size);
  if (!lppd->hDevNames)
    return E_FAIL;
  void* dev_names_ptr = GlobalLock(lppd->hDevNames);
  if (!dev_names_ptr)
    return E_FAIL;
  DEVNAMES* dev_names = reinterpret_cast<DEVNAMES*>(dev_names_ptr);
  dev_names->wDefault = 1;
  dev_names->wDriverOffset = sizeof(DEVNAMES);
  memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDriverOffset,
      info_2->pDriverName, driver_size);
  dev_names->wDeviceOffset = dev_names->wDriverOffset + driver_size;
  memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDeviceOffset,
      info_2->pPrinterName, printer_size);
  dev_names->wOutputOffset = dev_names->wDeviceOffset + printer_size;
  memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wOutputOffset,
      info_2->pPortName, port_size);
  GlobalUnlock(lppd->hDevNames);

  return S_OK;
}

TEST_F(PrintingContextTest, Base) {
  printing::PrintSettings settings;

  settings.set_device_name(GetDefaultPrinter());
  // Initialize it.
  scoped_ptr<printing::PrintingContext> context(
      printing::PrintingContext::Create());
  EXPECT_EQ(printing::PrintingContext::OK, context->InitWithSettings(settings));

  // The print may lie to use and may not support world transformation.
  // Verify right now.
  XFORM random_matrix = { 1, 0.1f, 0, 1.5f, 0, 1 };
  EXPECT_TRUE(SetWorldTransform(context->context(), &random_matrix));
  EXPECT_TRUE(ModifyWorldTransform(context->context(), NULL, MWT_IDENTITY));
}

// http://crbug.com/61499
TEST_F(PrintingContextTest, FLAKY_PrintAll) {
  printing::PrintingContextWin context;
  context.SetPrintDialog(&PrintDlgExMock);
  context.AskUserForSettings(
      NULL,
      123,
      false,
      NewCallback(static_cast<PrintingContextTest*>(this),
                  &PrintingContextTest::PrintSettingsCallback));
  ASSERT_EQ(printing::PrintingContext::OK, result());
  printing::PrintSettings settings = context.settings();
  EXPECT_EQ(settings.ranges.size(), 0);
}
<commit_msg>Disable PrintingContextTest.Base on win<commit_after>// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <ocidl.h>
#include <commdlg.h>

#include <string>

#include "base/scoped_ptr.h"
#include "printing/printing_test.h"
#include "printing/printing_context.h"
#include "printing/printing_context_win.h"
#include "printing/print_settings.h"
#include "testing/gtest/include/gtest/gtest.h"

// This test is automatically disabled if no printer is available.
class PrintingContextTest : public PrintingTest<testing::Test> {
 public:
  void PrintSettingsCallback(printing::PrintingContext::Result result) {
    result_ = result;
  }

 protected:
  printing::PrintingContext::Result result() const { return result_; }

 private:
  printing::PrintingContext::Result result_;
};

// This is a fake PrintDlgEx implementation that sets the right fields in
// |lppd| to trigger a bug in older revisions of PrintingContext.
HRESULT WINAPI PrintDlgExMock(LPPRINTDLGEX lppd) {
  // The interesting bits:
  // Pretend the user hit print
  lppd->dwResultAction = PD_RESULT_PRINT;

  // Pretend the page range is 1-5, but since lppd->Flags does not have
  // PD_SELECTION set, this really shouldn't matter.
  lppd->nPageRanges = 1;
  lppd->lpPageRanges = new PRINTPAGERANGE[1];
  lppd->lpPageRanges[0].nFromPage = 1;
  lppd->lpPageRanges[0].nToPage = 5;

  // Painful paperwork.
  std::wstring printer_name = PrintingContextTest::GetDefaultPrinter();
  HANDLE printer;
  if (!OpenPrinter(const_cast<wchar_t*>(printer_name.c_str()), &printer, NULL))
    return E_FAIL;

  scoped_array<uint8> buffer;
  DEVMODE* dev_mode = NULL;
  PRINTER_INFO_2* info_2 = NULL;

  printing::PrintingContextWin::GetPrinterHelper(printer, 2, &buffer);
  if (buffer.get()) {
    info_2 = reinterpret_cast<PRINTER_INFO_2*>(buffer.get());
    if (info_2->pDevMode != NULL)
      dev_mode = info_2->pDevMode;
  }
  if (!dev_mode)
    return E_FAIL;

  if (!printing::PrintingContextWin::AllocateContext(printer_name, dev_mode,
      &lppd->hDC)) {
    return E_FAIL;
  }

  size_t dev_mode_size = dev_mode->dmSize + dev_mode->dmDriverExtra;
  lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, dev_mode_size);
  if (!lppd->hDevMode)
    return E_FAIL;
  void* dev_mode_ptr = GlobalLock(lppd->hDevMode);
  if (!dev_mode_ptr)
    return E_FAIL;
  memcpy(dev_mode_ptr, dev_mode, dev_mode_size);
  GlobalUnlock(lppd->hDevMode);

  size_t driver_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pDriverName);
  size_t printer_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pPrinterName);
  size_t port_size = 2 + sizeof(wchar_t) * lstrlen(info_2->pPortName);
  size_t dev_names_size = sizeof(DEVNAMES) + driver_size + printer_size +
      port_size;
  lppd->hDevNames = GlobalAlloc(GHND, dev_names_size);
  if (!lppd->hDevNames)
    return E_FAIL;
  void* dev_names_ptr = GlobalLock(lppd->hDevNames);
  if (!dev_names_ptr)
    return E_FAIL;
  DEVNAMES* dev_names = reinterpret_cast<DEVNAMES*>(dev_names_ptr);
  dev_names->wDefault = 1;
  dev_names->wDriverOffset = sizeof(DEVNAMES);
  memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDriverOffset,
      info_2->pDriverName, driver_size);
  dev_names->wDeviceOffset = dev_names->wDriverOffset + driver_size;
  memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDeviceOffset,
      info_2->pPrinterName, printer_size);
  dev_names->wOutputOffset = dev_names->wDeviceOffset + printer_size;
  memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wOutputOffset,
      info_2->pPortName, port_size);
  GlobalUnlock(lppd->hDevNames);

  return S_OK;
}

// crbug.com/61509
TEST_F(PrintingContextTest, FLAKY_Base) {
  printing::PrintSettings settings;

  settings.set_device_name(GetDefaultPrinter());
  // Initialize it.
  scoped_ptr<printing::PrintingContext> context(
      printing::PrintingContext::Create());
  EXPECT_EQ(printing::PrintingContext::OK, context->InitWithSettings(settings));

  // The print may lie to use and may not support world transformation.
  // Verify right now.
  XFORM random_matrix = { 1, 0.1f, 0, 1.5f, 0, 1 };
  EXPECT_TRUE(SetWorldTransform(context->context(), &random_matrix));
  EXPECT_TRUE(ModifyWorldTransform(context->context(), NULL, MWT_IDENTITY));
}

// http://crbug.com/61499
TEST_F(PrintingContextTest, FLAKY_PrintAll) {
  printing::PrintingContextWin context;
  context.SetPrintDialog(&PrintDlgExMock);
  context.AskUserForSettings(
      NULL,
      123,
      false,
      NewCallback(static_cast<PrintingContextTest*>(this),
                  &PrintingContextTest::PrintSettingsCallback));
  ASSERT_EQ(printing::PrintingContext::OK, result());
  printing::PrintSettings settings = context.settings();
  EXPECT_EQ(settings.ranges.size(), 0);
}
<|endoftext|>


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

#include <algorithm>

#include <vector>

#include "base/callback.h"
#include "base/util.h"

#include "graph/graph.h"

namespace operations_research {

namespace {
// TODO(user) : rewrite this algorithm without the recursivity.
void Search(ResultCallback2<bool, int, int>* const graph,
            ResultCallback1<bool, const vector<int>&>* const callback,
            int* input_candidates,
            int input_size,
            int input_candidate_size,
            vector<int>* actual,
            bool* stop) {
  vector<int> actual_candidates(input_candidate_size);
  int pre_increment = 0;
  int pivot = 0;
  int actual_candidate_size;
  int actual_size;
  int start = 0;
  int index = input_candidate_size;

  // Find Pivot.
  for (int i = 0; i < input_candidate_size && index != 0; ++i) {
    int p = input_candidates[i];
    int count = 0;
    int position = 0;

    // Count disconnections.
    for (int j = input_size; j < input_candidate_size && count < index; ++j) {
      if (!graph->Run(p, input_candidates[j])) {
        count++;
        // Save position of potential candidate.
        position = j;
      }
    }

    // Test new minimum.
    if (count < index) {
      pivot = p;
      index = count;

      if (i < input_size) {
        start = position;
      } else {
        start = i;
        // pre increment obvious candidate.
        pre_increment = 1;
      }
    }
  }

  // If fixed point initially chosen from candidates then
  // number of diconnections will be preincreased by one
  // Backtracking step for all nodes in the candidate list CD.
  for (int nod = index + pre_increment; nod >= 1; nod--) {
    // Swap.
    int selected = input_candidates[start];
    input_candidates[start] = input_candidates[input_size];
    input_candidates[input_size] = selected;

    // Fill new set "not".
    actual_candidate_size = 0;

    for (int i = 0; i < input_size; ++i) {
      if (graph->Run(selected, input_candidates[i])) {
        actual_candidates[actual_candidate_size++] = input_candidates[i];
      }
    }

    // Fill new set "candidates".
    actual_size = actual_candidate_size;

    for (int i = input_size + 1; i < input_candidate_size; ++i) {
      if (graph->Run(selected, input_candidates[i])) {
        actual_candidates[actual_size++] = input_candidates[i];
      }
    }

    // Add to "actual relevant nodes".
    actual->push_back(selected);

    // We have found a maximum clique.
    if (actual_size == 0) {
      *stop = callback->Run(*actual);
    } else {
      if (actual_candidate_size < actual_size) {
         Search(graph, callback, actual_candidates.data(),
                actual_candidate_size, actual_size, actual, stop);
        if (*stop) {
          return;
        }
      }
    }

    // move node from MD to ND
    // Remove from compsub
    actual->pop_back();

    // Add to "nod"
    input_size++;

    if (nod > 1) {
      // Select a candidate disgraph to the fixed point
      start = input_size;
      while (graph->Run(pivot, input_candidates[start])) {
        start++;
      }
    }
    // end selection
  }
}

#if defined(_MSC_VER)
// The following class defines a hash function for arcs
class IntPairHasher : public stdext::hash_compare <Arc> {
 public:
  size_t operator() (const pair<int, int>& a) const {
    uint64 x = a.first;
    uint64 y = GG_ULONGLONG(0xe08c1d668b756f82);
    uint64 z = a.second;
    mix(x, y, z);
    return z;
  }
  bool operator() (const pair<int, int>& a1, const pair<int, int>& a2) const {
    return a1.first < a2.first ||
        (a1.first == a2.first && a1.second < a2.second);
  }
};
#endif

class FindAndEliminate {
 public:
  FindAndEliminate(ResultCallback2<bool, int, int>* const graph,
                   int node_count,
                   ResultCallback1<bool, const vector<int>&>* const callback)
      : graph_(graph), node_count_(node_count), callback_(callback) {}

  bool GraphCallback(int node1, int node2) {
    if (visited_.find(make_pair(std::min(node1, node2),
                                std::max(node1, node2))) != visited_.end()) {
      return false;
    }
    return graph_->Run(node1, node2);
  }

  bool SolutionCallback(const vector<int>& solution) {
    const int size = solution.size();
    if (size > 1) {
      for (int i = 0; i < size - 1; ++i) {
        for (int j = i + 1; j < size; ++j) {
          visited_.insert(make_pair(std::min(solution[i], solution[j]),
                                    std::max(solution[i], solution[j])));
        }
      }
      callback_->Run(solution);
    }
    return false;
  }
 private:
  ResultCallback2<bool, int, int>* const graph_;
  int node_count_;
  ResultCallback1<bool, const vector<int>&>* const callback_;
#if defined(_MSC_VER)
  hash_set<pair<int, int>, IntPairHasher> visited_;
#else
  hash_set<pair<int, int> > visited_;
#endif
};
}  // namespace

// This method implements the 'version2' of the Bron-Kerbosch
// algorithm to find all maximal cliques in a undirected graph.
void FindCliques(ResultCallback2<bool, int, int>* const graph,
                 int node_count,
                 ResultCallback1<bool, const vector<int>&>* const callback) {
  graph->CheckIsRepeatable();
  callback->CheckIsRepeatable();
  scoped_array<int> initial_candidates(new int[node_count]);
  vector<int> actual;

  scoped_ptr<ResultCallback2<bool, int, int> > graph_deleter(graph);
  scoped_ptr<ResultCallback1<bool, const vector<int>&> > callback_deleter(
      callback);

  for (int c = 0; c < node_count; ++c) {
    initial_candidates[c] = c;
  }

  bool stop = false;
  Search(graph, callback, initial_candidates.get(), 0, node_count, &actual,
         &stop);
}

void CoverArcsByCliques(
    ResultCallback2<bool, int, int>* const graph,
    int node_count,
    ResultCallback1<bool, const vector<int>&>* const callback) {
  graph->CheckIsRepeatable();
  callback->CheckIsRepeatable();

  scoped_ptr<ResultCallback2<bool, int, int> > graph_deleter(graph);
  scoped_ptr<ResultCallback1<bool, const vector<int>&> > callback_deleter(
      callback);

  FindAndEliminate cache(graph, node_count, callback);
  scoped_array<int> initial_candidates(new int[node_count]);
  vector<int> actual;

  scoped_ptr<ResultCallback2<bool, int, int> > cached_graph(
      NewPermanentCallback(&cache, &FindAndEliminate::GraphCallback));
  scoped_ptr<ResultCallback1<bool, const vector<int>&> >cached_callback(
      NewPermanentCallback(&cache, &FindAndEliminate::SolutionCallback));

  for (int c = 0; c < node_count; ++c) {
    initial_candidates[c] = c;
  }

  bool stop = false;
  Search(cached_graph.get(), cached_callback.get(),
         initial_candidates.get(), 0,
         node_count, &actual, &stop);
}

}  // namespace operations_research
<commit_msg>fix visual studio compilation<commit_after>// Copyright 2010 Google
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <algorithm>

#include <vector>

#include "base/callback.h"
#include "base/util.h"

#include "graph/graph.h"

namespace operations_research {

namespace {
// TODO(user) : rewrite this algorithm without the recursivity.
void Search(ResultCallback2<bool, int, int>* const graph,
            ResultCallback1<bool, const vector<int>&>* const callback,
            int* input_candidates,
            int input_size,
            int input_candidate_size,
            vector<int>* actual,
            bool* stop) {
  vector<int> actual_candidates(input_candidate_size);
  int pre_increment = 0;
  int pivot = 0;
  int actual_candidate_size;
  int actual_size;
  int start = 0;
  int index = input_candidate_size;

  // Find Pivot.
  for (int i = 0; i < input_candidate_size && index != 0; ++i) {
    int p = input_candidates[i];
    int count = 0;
    int position = 0;

    // Count disconnections.
    for (int j = input_size; j < input_candidate_size && count < index; ++j) {
      if (!graph->Run(p, input_candidates[j])) {
        count++;
        // Save position of potential candidate.
        position = j;
      }
    }

    // Test new minimum.
    if (count < index) {
      pivot = p;
      index = count;

      if (i < input_size) {
        start = position;
      } else {
        start = i;
        // pre increment obvious candidate.
        pre_increment = 1;
      }
    }
  }

  // If fixed point initially chosen from candidates then
  // number of diconnections will be preincreased by one
  // Backtracking step for all nodes in the candidate list CD.
  for (int nod = index + pre_increment; nod >= 1; nod--) {
    // Swap.
    int selected = input_candidates[start];
    input_candidates[start] = input_candidates[input_size];
    input_candidates[input_size] = selected;

    // Fill new set "not".
    actual_candidate_size = 0;

    for (int i = 0; i < input_size; ++i) {
      if (graph->Run(selected, input_candidates[i])) {
        actual_candidates[actual_candidate_size++] = input_candidates[i];
      }
    }

    // Fill new set "candidates".
    actual_size = actual_candidate_size;

    for (int i = input_size + 1; i < input_candidate_size; ++i) {
      if (graph->Run(selected, input_candidates[i])) {
        actual_candidates[actual_size++] = input_candidates[i];
      }
    }

    // Add to "actual relevant nodes".
    actual->push_back(selected);

    // We have found a maximum clique.
    if (actual_size == 0) {
      *stop = callback->Run(*actual);
    } else {
      if (actual_candidate_size < actual_size) {
         Search(graph, callback, actual_candidates.data(),
                actual_candidate_size, actual_size, actual, stop);
        if (*stop) {
          return;
        }
      }
    }

    // move node from MD to ND
    // Remove from compsub
    actual->pop_back();

    // Add to "nod"
    input_size++;

    if (nod > 1) {
      // Select a candidate disgraph to the fixed point
      start = input_size;
      while (graph->Run(pivot, input_candidates[start])) {
        start++;
      }
    }
    // end selection
  }
}

#if defined(_MSC_VER)
// The following class defines a hash function for arcs
class IntPairHasher : public stdext::hash_compare <pair<int, int> > {
 public:
  size_t operator() (const pair<int, int>& a) const {
    uint64 x = a.first;
    uint64 y = GG_ULONGLONG(0xe08c1d668b756f82);
    uint64 z = a.second;
    mix(x, y, z);
    return z;
  }
  bool operator() (const pair<int, int>& a1, const pair<int, int>& a2) const {
    return a1.first < a2.first ||
        (a1.first == a2.first && a1.second < a2.second);
  }
};
#endif

class FindAndEliminate {
 public:
  FindAndEliminate(ResultCallback2<bool, int, int>* const graph,
                   int node_count,
                   ResultCallback1<bool, const vector<int>&>* const callback)
      : graph_(graph), node_count_(node_count), callback_(callback) {}

  bool GraphCallback(int node1, int node2) {
    if (visited_.find(make_pair(std::min(node1, node2),
                                std::max(node1, node2))) != visited_.end()) {
      return false;
    }
    return graph_->Run(node1, node2);
  }

  bool SolutionCallback(const vector<int>& solution) {
    const int size = solution.size();
    if (size > 1) {
      for (int i = 0; i < size - 1; ++i) {
        for (int j = i + 1; j < size; ++j) {
          visited_.insert(make_pair(std::min(solution[i], solution[j]),
                                    std::max(solution[i], solution[j])));
        }
      }
      callback_->Run(solution);
    }
    return false;
  }
 private:
  ResultCallback2<bool, int, int>* const graph_;
  int node_count_;
  ResultCallback1<bool, const vector<int>&>* const callback_;
#if defined(_MSC_VER)
  hash_set<pair<int, int>, IntPairHasher> visited_;
#else
  hash_set<pair<int, int> > visited_;
#endif
};
}  // namespace

// This method implements the 'version2' of the Bron-Kerbosch
// algorithm to find all maximal cliques in a undirected graph.
void FindCliques(ResultCallback2<bool, int, int>* const graph,
                 int node_count,
                 ResultCallback1<bool, const vector<int>&>* const callback) {
  graph->CheckIsRepeatable();
  callback->CheckIsRepeatable();
  scoped_array<int> initial_candidates(new int[node_count]);
  vector<int> actual;

  scoped_ptr<ResultCallback2<bool, int, int> > graph_deleter(graph);
  scoped_ptr<ResultCallback1<bool, const vector<int>&> > callback_deleter(
      callback);

  for (int c = 0; c < node_count; ++c) {
    initial_candidates[c] = c;
  }

  bool stop = false;
  Search(graph, callback, initial_candidates.get(), 0, node_count, &actual,
         &stop);
}

void CoverArcsByCliques(
    ResultCallback2<bool, int, int>* const graph,
    int node_count,
    ResultCallback1<bool, const vector<int>&>* const callback) {
  graph->CheckIsRepeatable();
  callback->CheckIsRepeatable();

  scoped_ptr<ResultCallback2<bool, int, int> > graph_deleter(graph);
  scoped_ptr<ResultCallback1<bool, const vector<int>&> > callback_deleter(
      callback);

  FindAndEliminate cache(graph, node_count, callback);
  scoped_array<int> initial_candidates(new int[node_count]);
  vector<int> actual;

  scoped_ptr<ResultCallback2<bool, int, int> > cached_graph(
      NewPermanentCallback(&cache, &FindAndEliminate::GraphCallback));
  scoped_ptr<ResultCallback1<bool, const vector<int>&> >cached_callback(
      NewPermanentCallback(&cache, &FindAndEliminate::SolutionCallback));

  for (int c = 0; c < node_count; ++c) {
    initial_candidates[c] = c;
  }

  bool stop = false;
  Search(cached_graph.get(), cached_callback.get(),
         initial_candidates.get(), 0,
         node_count, &actual, &stop);
}

}  // namespace operations_research
<|endoftext|>