<commit_before>/*
				Copyright <SWGEmu>
		See file COPYING for copying conditions. */

#include "templates/params/creature/CreatureAttribute.h"
#include "templates/params/creature/CreatureState.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/creature/commands/effect/CommandEffect.h"
#include "DamageOverTime.h"
#include "server/zone/Zone.h"
#include "server/zone/ZoneServer.h"
#include "server/zone/packets/object/CombatSpam.h"

DamageOverTime::DamageOverTime() {
	setAttackerID(0);
	setType(CreatureState::BLEEDING);
	setAttribute(CreatureAttribute::HEALTH);
	strength = 0;
	setDuration(0);
	setExpires(0);
	setSecondaryStrength(0);
	addSerializableVariables();
}

DamageOverTime::DamageOverTime(CreatureObject* attacker,
							   uint64 tp,
							   uint8 attrib,
							   uint32 str,
							   uint32 dur,
							   int secondaryStrength) {

	if (attacker != NULL)
		setAttackerID(attacker->getObjectID());

	setType(tp);
	setAttribute(attrib);
	strength = str;
	setDuration(dur);
	setSecondaryStrength(secondaryStrength);
	applied.updateToCurrentTime();
	activate();

	addSerializableVariables();
}

DamageOverTime::DamageOverTime(const DamageOverTime& dot) : Object(), Serializable() {
	addSerializableVariables();

	attackerID = dot.attackerID;
	type = dot.type;
	attribute = dot.attribute;
	strength = dot.strength;
	duration = dot.duration;
	applied = dot.applied;
	expires = dot.expires;
	nextTick = dot.nextTick;
	secondaryStrength = dot.secondaryStrength;

}

DamageOverTime& DamageOverTime::operator=(const DamageOverTime& dot) {
	if (this == &dot)
		return *this;

	attackerID = dot.attackerID;
	type = dot.type;
	attribute = dot.attribute;
	strength = dot.strength;
	duration = dot.duration;
	applied = dot.applied;
	expires = dot.expires;
	nextTick = dot.nextTick;
	secondaryStrength = dot.secondaryStrength;

	return *this;
}

void DamageOverTime::addSerializableVariables() {
	addSerializableVariable("attackerID", &attackerID);
	addSerializableVariable("type", &type);
	addSerializableVariable("attribute", &attribute);
	addSerializableVariable("strength", &strength);
	addSerializableVariable("duration", &duration);
	addSerializableVariable("applied", &applied);
	addSerializableVariable("expires", &expires);
	addSerializableVariable("nextTick", &nextTick);
	addSerializableVariable("secondaryStrength", &secondaryStrength);

}

void DamageOverTime::activate() {
	expires.updateToCurrentTime();
	expires.addMiliTime(duration * 1000);
}

uint32 DamageOverTime::applyDot(CreatureObject* victim) {
	if (expires.isPast() || !nextTick.isPast())
		return 0;

	nextTick.updateToCurrentTime();

	uint32 power = 0;
	ManagedReference<CreatureObject*> attacker = victim->getZoneServer()->getObject(attackerID).castTo<CreatureObject*>();

	if (attacker == NULL)
		attacker = victim;

	switch(type) {
	case CreatureState::BLEEDING:
		power = doBleedingTick(victim, attacker);
		nextTick.addMiliTime(20000);
		break;
	case CreatureState::POISONED:
		power = doPoisonTick(victim, attacker);
		nextTick.addMiliTime(10000);
		break;
	case CreatureState::DISEASED:
		power = doDiseaseTick(victim, attacker);
		nextTick.addMiliTime(40000);
		break;
	case CreatureState::ONFIRE:
		power = doFireTick(victim, attacker);
		nextTick.addMiliTime(10000);
		break;
	case CommandEffect::FORCECHOKE:
		power = doForceChokeTick(victim, attacker);
		nextTick.addMiliTime(6000);
		break;
	}

	return power;
}

uint32 DamageOverTime::initDot(CreatureObject* victim, CreatureObject* attacker) {
	uint32 power = 0;
	int absorptionMod = 0;
	nextTick.updateToCurrentTime();

	switch(type) {
	case CreatureState::BLEEDING:
		absorptionMod = MIN(0, MAX(50, victim->getSkillMod("absorption_bleeding")));
		nextTick.addMiliTime(20000);
		break;
	case CreatureState::POISONED:
		absorptionMod = MIN(0, MAX(50, victim->getSkillMod("absorption_poison")));
		nextTick.addMiliTime(10000);
		break;
	case CreatureState::ONFIRE:
		absorptionMod = MIN(0, MAX(50, victim->getSkillMod("absorption_fire")));
		nextTick.addMiliTime(10000);
		break;
	case CreatureState::DISEASED:
		absorptionMod = MIN(0, MAX(50, victim->getSkillMod("absorption_disease")));
		nextTick.addMiliTime(40000);
		break;
	case CommandEffect::FORCECHOKE:
		nextTick.addMiliTime(6000);
		strength = (float)(strength * 0.01f) + (strength * (System::random(100) * 0.01f));
		victim->showFlyText("combat_effects", "choke", 0xFF, 0, 0);

		break;
	}

	power = (uint32)(strength * (1.f - absorptionMod / 100.f));

	//victim->addDamage(attacker,1);

	return power;
}

uint32 DamageOverTime::doBleedingTick(CreatureObject* victim, CreatureObject* attacker) {
	// TODO: Do we try to resist again?
	// we need to allow dots to tick while incapped, but not do damage
	if (victim->isIncapacitated() && victim->isFeigningDeath() == false)
		return 0;

	uint32 attr = victim->getHAM(attribute);
	int absorptionMod = MIN(0, MAX(50, victim->getSkillMod("absorption_bleeding")));

	// absorption reduces the strength of a dot by the given %.
	int damage = (int)(strength * (1.f - absorptionMod / 100.f));
	if (attr < damage) {
		//System::out << "setting strength to " << attr -1 << endl;
		damage = attr - 1;
	}

	Reference<CreatureObject*> attackerRef = attacker;
	Reference<CreatureObject*> victimRef = victim;
	uint8 attribute = this->attribute;

	EXECUTE_TASK_4(attackerRef, victimRef, attribute, damage, {
			Locker locker(victimRef_p);

			Locker crossLocker(attackerRef_p, victimRef_p);

			victimRef_p->inflictDamage(attackerRef_p, attribute_p, damage_p, false);

			if (victimRef_p->hasAttackDelay())
				victimRef_p->removeAttackDelay();

			victimRef_p->playEffect("clienteffect/dot_bleeding.cef","");
	});

	return damage;
}

uint32 DamageOverTime::doFireTick(CreatureObject* victim, CreatureObject* attacker) {
	// we need to allow dots to tick while incapped, but not do damage
	if (victim->isIncapacitated() && victim->isFeigningDeath() == false)
		return 0;

	uint32 attr = victim->getHAM(attribute);
	int absorptionMod = MIN(0, MAX(50, victim->getSkillMod("absorption_fire")));

	// absorption reduces the strength of a dot by the given %.
	int damage = (int)(strength * (1.f - absorptionMod / 100.f));
	if (attr < damage) {
		//System::out << "setting strength to " << attr -1 << endl;
		damage = attr - 1;
	}

	int woundsToApply = (int)(secondaryStrength * (1.f + victim->getShockWounds() / 100.0f));
	int maxWoundsToApply = victim->getBaseHAM(attribute) - 1 - victim->getWounds(attribute);

	woundsToApply = MIN(woundsToApply, maxWoundsToApply);

	Reference<CreatureObject*> attackerRef = attacker;
	Reference<CreatureObject*> victimRef = victim;
	uint8 attribute = this->attribute;
	uint32 strength = this->strength;
	uint32 secondaryStrength = this->secondaryStrength;

	EXECUTE_TASK_6(attackerRef, victimRef, attribute, damage, woundsToApply, secondaryStrength, {
			Locker locker(victimRef_p);

			Locker crossLocker(attackerRef_p, victimRef_p);

			if (woundsToApply_p > 0)
			{
				// need to do damage to account for wounds first, or it will possibly get
				// applied twice
				if (attribute_p % 3 == 0)
					victimRef_p->inflictDamage(attackerRef_p, attribute_p, woundsToApply_p, true);

				victimRef_p->addWounds(attribute_p, woundsToApply_p, true, false);
			}

			victimRef_p->addShockWounds((int)(secondaryStrength_p * 0.075f));

			victimRef_p->inflictDamage(attackerRef_p, attribute_p - attribute_p % 3, damage_p, true);
			if (victimRef_p->hasAttackDelay())
				victimRef_p->removeAttackDelay();

			victimRef_p->playEffect("clienteffect/dot_fire.cef","");
	});

	return damage;
}

uint32 DamageOverTime::doPoisonTick(CreatureObject* victim, CreatureObject* attacker) {
	// we need to allow dots to tick while incapped, but not do damage
	if (victim->isIncapacitated() && victim->isFeigningDeath() == false)
		return 0;

	uint32 attr = victim->getHAM(attribute);
	int absorptionMod = MIN(0, MAX(50, victim->getSkillMod("absorption_poison")));

	// absorption reduces the strength of a dot by the given %.
	int damage = (int)(strength * (1.f - absorptionMod / 100.f));
	if (attr < damage) {
		//System::out << "setting strength to " << attr -1 << endl;
		damage = attr - 1;
	}

	Reference<CreatureObject*> attackerRef = attacker;
	Reference<CreatureObject*> victimRef = victim;
	uint8 attribute = this->attribute;

	EXECUTE_TASK_4(attackerRef, victimRef, attribute, damage, {
			Locker locker(victimRef_p);

			Locker crossLocker(attackerRef_p, victimRef_p);

			victimRef_p->inflictDamage(attackerRef_p, attribute_p, damage_p, false);
			if (victimRef_p->hasAttackDelay())
				victimRef_p->removeAttackDelay();

			victimRef_p->playEffect("clienteffect/dot_poisoned.cef","");
	});

	return damage;
}

uint32 DamageOverTime::doDiseaseTick(CreatureObject* victim, CreatureObject* attacker) {
	// we need to allow dots to tick while incapped, but not do damage
	if (victim->isIncapacitated() && victim->isFeigningDeath() == false)
		return 0;

	int absorptionMod = MIN(0, MAX(50, victim->getSkillMod("absorption_disease")));

	// absorption reduces the strength of a dot by the given %.
	// make sure that the CM dots modify the strength
	int damage = (int)(strength * (1.f - absorptionMod / 100.f) * (1.f + victim->getShockWounds() / 100.0f));
	int maxDamage = victim->getBaseHAM(attribute) - 1 - victim->getWounds(attribute);

	damage = MIN(damage, maxDamage);

	uint8 attribute = this->attribute;
	uint32 strength = this->strength;
	Reference<CreatureObject*> attackerRef = attacker;
	Reference<CreatureObject*> victimRef = victim;

	EXECUTE_TASK_5(attackerRef, victimRef, attribute, strength, damage, {
			Locker locker(victimRef_p);
			Locker crossLocker(attackerRef_p, victimRef_p);

			if ((int)damage_p > 0) {
				// need to do damage to account for wounds first, or it will possibly get
				// applied twice
				if (attribute_p % 3 == 0)
					victimRef_p->inflictDamage(attackerRef_p, attribute_p, damage_p, true);

				victimRef_p->addWounds(attribute_p, damage_p, true, false);
			}

			victimRef_p->addShockWounds((int)(strength_p * 0.075f));

			if (victimRef_p->hasAttackDelay())
				victimRef_p->removeAttackDelay();

			victimRef_p->playEffect("clienteffect/dot_diseased.cef","");
	});

	return damage;
}

uint32 DamageOverTime::doForceChokeTick(CreatureObject* victim, CreatureObject* attacker) {
	// we need to allow dots to tick while incapped, but not do damage
	if (victim->isIncapacitated() && victim->isFeigningDeath() == false)
		return 0;

	Reference<CreatureObject*> attackerRef = attacker;
	Reference<CreatureObject*> victimRef = victim;

	EXECUTE_TASK_4(victimRef, attackerRef, attribute, strength, {
			Locker locker(victimRef_p);

			Locker crossLocker(attackerRef_p, victimRef_p);

			victimRef_p->inflictDamage(attackerRef_p, attribute_p, strength_p, true);
			if (victimRef_p->hasAttackDelay())
				victimRef_p->removeAttackDelay();

			victimRef_p->playEffect("clienteffect/pl_force_choke.cef", "");
			victimRef_p->sendSystemMessage("@combat_effects:choke_single");
	});

	return strength;

}

float DamageOverTime::reduceTick(float reduction) {
	//System::out << "reducing tick with reduction " << reduction << endl;
	if (reduction < 0.f) // this ensures we can't increase a dot strength
		return reduction;

	if (reduction >= strength) {
		expireTick();
		return reduction - strength;
	} else {
		//System::out << "strength before dotRed " << strength << endl;
		strength -= reduction;
		//System::out << "strength after dotRed " << strength << endl;
	}

	return 0.f;
}

void DamageOverTime::multiplyDuration(float multiplier) {
	Time newTime;
	uint64 timeToAdd = (expires.getMiliTime() - newTime.getMiliTime()) * multiplier;
	newTime.addMiliTime(timeToAdd);
	expires = newTime;

}
<commit_msg>[fixed] the dot 'absorption' mod to function properly (Mantis #7020)<commit_after>/*
				Copyright <SWGEmu>
		See file COPYING for copying conditions. */

#include "templates/params/creature/CreatureAttribute.h"
#include "templates/params/creature/CreatureState.h"
#include "server/zone/objects/creature/CreatureObject.h"
#include "server/zone/objects/creature/commands/effect/CommandEffect.h"
#include "DamageOverTime.h"
#include "server/zone/Zone.h"
#include "server/zone/ZoneServer.h"
#include "server/zone/packets/object/CombatSpam.h"

DamageOverTime::DamageOverTime() {
	setAttackerID(0);
	setType(CreatureState::BLEEDING);
	setAttribute(CreatureAttribute::HEALTH);
	strength = 0;
	setDuration(0);
	setExpires(0);
	setSecondaryStrength(0);
	addSerializableVariables();
}

DamageOverTime::DamageOverTime(CreatureObject* attacker,
							   uint64 tp,
							   uint8 attrib,
							   uint32 str,
							   uint32 dur,
							   int secondaryStrength) {

	if (attacker != NULL)
		setAttackerID(attacker->getObjectID());

	setType(tp);
	setAttribute(attrib);
	strength = str;
	setDuration(dur);
	setSecondaryStrength(secondaryStrength);
	applied.updateToCurrentTime();
	activate();

	addSerializableVariables();
}

DamageOverTime::DamageOverTime(const DamageOverTime& dot) : Object(), Serializable() {
	addSerializableVariables();

	attackerID = dot.attackerID;
	type = dot.type;
	attribute = dot.attribute;
	strength = dot.strength;
	duration = dot.duration;
	applied = dot.applied;
	expires = dot.expires;
	nextTick = dot.nextTick;
	secondaryStrength = dot.secondaryStrength;

}

DamageOverTime& DamageOverTime::operator=(const DamageOverTime& dot) {
	if (this == &dot)
		return *this;

	attackerID = dot.attackerID;
	type = dot.type;
	attribute = dot.attribute;
	strength = dot.strength;
	duration = dot.duration;
	applied = dot.applied;
	expires = dot.expires;
	nextTick = dot.nextTick;
	secondaryStrength = dot.secondaryStrength;

	return *this;
}

void DamageOverTime::addSerializableVariables() {
	addSerializableVariable("attackerID", &attackerID);
	addSerializableVariable("type", &type);
	addSerializableVariable("attribute", &attribute);
	addSerializableVariable("strength", &strength);
	addSerializableVariable("duration", &duration);
	addSerializableVariable("applied", &applied);
	addSerializableVariable("expires", &expires);
	addSerializableVariable("nextTick", &nextTick);
	addSerializableVariable("secondaryStrength", &secondaryStrength);

}

void DamageOverTime::activate() {
	expires.updateToCurrentTime();
	expires.addMiliTime(duration * 1000);
}

uint32 DamageOverTime::applyDot(CreatureObject* victim) {
	if (expires.isPast() || !nextTick.isPast())
		return 0;

	nextTick.updateToCurrentTime();

	uint32 power = 0;
	ManagedReference<CreatureObject*> attacker = victim->getZoneServer()->getObject(attackerID).castTo<CreatureObject*>();

	if (attacker == NULL)
		attacker = victim;

	switch(type) {
	case CreatureState::BLEEDING:
		power = doBleedingTick(victim, attacker);
		nextTick.addMiliTime(20000);
		break;
	case CreatureState::POISONED:
		power = doPoisonTick(victim, attacker);
		nextTick.addMiliTime(10000);
		break;
	case CreatureState::DISEASED:
		power = doDiseaseTick(victim, attacker);
		nextTick.addMiliTime(40000);
		break;
	case CreatureState::ONFIRE:
		power = doFireTick(victim, attacker);
		nextTick.addMiliTime(10000);
		break;
	case CommandEffect::FORCECHOKE:
		power = doForceChokeTick(victim, attacker);
		nextTick.addMiliTime(6000);
		break;
	}

	return power;
}

uint32 DamageOverTime::initDot(CreatureObject* victim, CreatureObject* attacker) {
	uint32 power = 0;
	int absorptionMod = 0;
	nextTick.updateToCurrentTime();

	switch(type) {
	case CreatureState::BLEEDING:
		absorptionMod = MAX(0, MIN(50, victim->getSkillMod("absorption_bleeding")));
		nextTick.addMiliTime(20000);
		break;
	case CreatureState::ONFIRE:
		absorptionMod = MAX(0, MIN(50, victim->getSkillMod("absorption_fire")));
		nextTick.addMiliTime(10000);
		break;
	case CreatureState::POISONED:
		absorptionMod = MAX(0, MIN(50, victim->getSkillMod("absorption_poison")));
		nextTick.addMiliTime(10000);
		break;
	case CreatureState::DISEASED:
		absorptionMod = MAX(0, MIN(50, victim->getSkillMod("absorption_disease")));
		nextTick.addMiliTime(40000);
		break;
	case CommandEffect::FORCECHOKE:
		nextTick.addMiliTime(6000);
		strength = (float)(strength * 0.01f) + (strength * (System::random(100) * 0.01f));
		victim->showFlyText("combat_effects", "choke", 0xFF, 0, 0);

		break;
	}

	power = (uint32)(strength * (1.f - absorptionMod / 100.f));

	//victim->addDamage(attacker,1);

	return power;
}

uint32 DamageOverTime::doBleedingTick(CreatureObject* victim, CreatureObject* attacker) {
	// TODO: Do we try to resist again?
	// we need to allow dots to tick while incapped, but not do damage
	if (victim->isIncapacitated() && victim->isFeigningDeath() == false)
		return 0;

	uint32 attr = victim->getHAM(attribute);
	int absorptionMod = MAX(0, MIN(50, victim->getSkillMod("absorption_bleeding")));

	// absorption reduces the strength of a dot by the given %.
	int damage = (int)(strength * (1.f - absorptionMod / 100.f));
	if (attr < damage) {
		//System::out << "setting strength to " << attr -1 << endl;
		damage = attr - 1;
	}

	Reference<CreatureObject*> attackerRef = attacker;
	Reference<CreatureObject*> victimRef = victim;
	uint8 attribute = this->attribute;

	EXECUTE_TASK_4(attackerRef, victimRef, attribute, damage, {
			Locker locker(victimRef_p);

			Locker crossLocker(attackerRef_p, victimRef_p);

			victimRef_p->inflictDamage(attackerRef_p, attribute_p, damage_p, false);

			if (victimRef_p->hasAttackDelay())
				victimRef_p->removeAttackDelay();

			victimRef_p->playEffect("clienteffect/dot_bleeding.cef","");
	});

	return damage;
}

uint32 DamageOverTime::doFireTick(CreatureObject* victim, CreatureObject* attacker) {
	// we need to allow dots to tick while incapped, but not do damage
	if (victim->isIncapacitated() && victim->isFeigningDeath() == false)
		return 0;

	uint32 attr = victim->getHAM(attribute);
	int absorptionMod = MAX(0, MIN(50, victim->getSkillMod("absorption_fire")));

	// absorption reduces the strength of a dot by the given %.
	int damage = (int)(strength * (1.f - absorptionMod / 100.f));
	if (attr < damage) {
		//System::out << "setting strength to " << attr -1 << endl;
		damage = attr - 1;
	}

	int woundsToApply = (int)(secondaryStrength * (1.f + victim->getShockWounds() / 100.0f));
	int maxWoundsToApply = victim->getBaseHAM(attribute) - 1 - victim->getWounds(attribute);

	woundsToApply = MIN(woundsToApply, maxWoundsToApply);

	Reference<CreatureObject*> attackerRef = attacker;
	Reference<CreatureObject*> victimRef = victim;
	uint8 attribute = this->attribute;
	uint32 strength = this->strength;
	uint32 secondaryStrength = this->secondaryStrength;

	EXECUTE_TASK_6(attackerRef, victimRef, attribute, damage, woundsToApply, secondaryStrength, {
			Locker locker(victimRef_p);

			Locker crossLocker(attackerRef_p, victimRef_p);

			if (woundsToApply_p > 0)
			{
				// need to do damage to account for wounds first, or it will possibly get
				// applied twice
				if (attribute_p % 3 == 0)
					victimRef_p->inflictDamage(attackerRef_p, attribute_p, woundsToApply_p, true);

				victimRef_p->addWounds(attribute_p, woundsToApply_p, true, false);
			}

			victimRef_p->addShockWounds((int)(secondaryStrength_p * 0.075f));

			victimRef_p->inflictDamage(attackerRef_p, attribute_p - attribute_p % 3, damage_p, true);
			if (victimRef_p->hasAttackDelay())
				victimRef_p->removeAttackDelay();

			victimRef_p->playEffect("clienteffect/dot_fire.cef","");
	});

	return damage;
}

uint32 DamageOverTime::doPoisonTick(CreatureObject* victim, CreatureObject* attacker) {
	// we need to allow dots to tick while incapped, but not do damage
	if (victim->isIncapacitated() && victim->isFeigningDeath() == false)
		return 0;

	uint32 attr = victim->getHAM(attribute);
	int absorptionMod = MAX(0, MIN(50, victim->getSkillMod("absorption_poison")));

	// absorption reduces the strength of a dot by the given %.
	int damage = (int)(strength * (1.f - absorptionMod / 100.f));
	if (attr < damage) {
		//System::out << "setting strength to " << attr -1 << endl;
		damage = attr - 1;
	}

	Reference<CreatureObject*> attackerRef = attacker;
	Reference<CreatureObject*> victimRef = victim;
	uint8 attribute = this->attribute;

	EXECUTE_TASK_4(attackerRef, victimRef, attribute, damage, {
			Locker locker(victimRef_p);

			Locker crossLocker(attackerRef_p, victimRef_p);

			victimRef_p->inflictDamage(attackerRef_p, attribute_p, damage_p, false);
			if (victimRef_p->hasAttackDelay())
				victimRef_p->removeAttackDelay();

			victimRef_p->playEffect("clienteffect/dot_poisoned.cef","");
	});

	return damage;
}

uint32 DamageOverTime::doDiseaseTick(CreatureObject* victim, CreatureObject* attacker) {
	// we need to allow dots to tick while incapped, but not do damage
	if (victim->isIncapacitated() && victim->isFeigningDeath() == false)
		return 0;

	int absorptionMod = MAX(0, MIN(50, victim->getSkillMod("absorption_disease")));

	// absorption reduces the strength of a dot by the given %.
	// make sure that the CM dots modify the strength
	int damage = (int)(strength * (1.f - absorptionMod / 100.f) * (1.f + victim->getShockWounds() / 100.0f));
	int maxDamage = victim->getBaseHAM(attribute) - 1 - victim->getWounds(attribute);

	damage = MIN(damage, maxDamage);

	uint8 attribute = this->attribute;
	uint32 strength = this->strength;
	Reference<CreatureObject*> attackerRef = attacker;
	Reference<CreatureObject*> victimRef = victim;

	EXECUTE_TASK_5(attackerRef, victimRef, attribute, strength, damage, {
			Locker locker(victimRef_p);
			Locker crossLocker(attackerRef_p, victimRef_p);

			if ((int)damage_p > 0) {
				// need to do damage to account for wounds first, or it will possibly get
				// applied twice
				if (attribute_p % 3 == 0)
					victimRef_p->inflictDamage(attackerRef_p, attribute_p, damage_p, true);

				victimRef_p->addWounds(attribute_p, damage_p, true, false);
			}

			victimRef_p->addShockWounds((int)(strength_p * 0.075f));

			if (victimRef_p->hasAttackDelay())
				victimRef_p->removeAttackDelay();

			victimRef_p->playEffect("clienteffect/dot_diseased.cef","");
	});

	return damage;
}

uint32 DamageOverTime::doForceChokeTick(CreatureObject* victim, CreatureObject* attacker) {
	// we need to allow dots to tick while incapped, but not do damage
	if (victim->isIncapacitated() && victim->isFeigningDeath() == false)
		return 0;

	Reference<CreatureObject*> attackerRef = attacker;
	Reference<CreatureObject*> victimRef = victim;

	EXECUTE_TASK_4(victimRef, attackerRef, attribute, strength, {
			Locker locker(victimRef_p);

			Locker crossLocker(attackerRef_p, victimRef_p);

			victimRef_p->inflictDamage(attackerRef_p, attribute_p, strength_p, true);
			if (victimRef_p->hasAttackDelay())
				victimRef_p->removeAttackDelay();

			victimRef_p->playEffect("clienteffect/pl_force_choke.cef", "");
			victimRef_p->sendSystemMessage("@combat_effects:choke_single");
	});

	return strength;

}

float DamageOverTime::reduceTick(float reduction) {
	//System::out << "reducing tick with reduction " << reduction << endl;
	if (reduction < 0.f) // this ensures we can't increase a dot strength
		return reduction;

	if (reduction >= strength) {
		expireTick();
		return reduction - strength;
	} else {
		//System::out << "strength before dotRed " << strength << endl;
		strength -= reduction;
		//System::out << "strength after dotRed " << strength << endl;
	}

	return 0.f;
}

void DamageOverTime::multiplyDuration(float multiplier) {
	Time newTime;
	uint64 timeToAdd = (expires.getMiliTime() - newTime.getMiliTime()) * multiplier;
	newTime.addMiliTime(timeToAdd);
	expires = newTime;

}
<|endoftext|>


<commit_before>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef __itkVoronoiSegmentationRGBImageFilter_hxx
#define __itkVoronoiSegmentationRGBImageFilter_hxx
#include "itkVoronoiSegmentationRGBImageFilter.h"

#include "itkImageRegionIteratorWithIndex.h"
#include <cmath>

namespace itk
{
/* Constructor: setting of the default values for the parameters. */
template< typename TInputImage, typename TOutputImage >
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::VoronoiSegmentationRGBImageFilter()
{
  unsigned int i;

  for ( i = 0; i < 6; i++ )
    {
    m_Mean[i] = 0;
    m_STD[i] = 0;
    m_MeanTolerance[i] = 10;
    m_STDTolerance[i] = 10;
    m_MeanPercentError[i] = 0.10;
    m_STDPercentError[i] = 1.5;
    }
//testing RGB for both mean and STD. (default).
  m_TestMean[0] = 0;
  m_TestMean[1] = 1;
  m_TestMean[2] = 2;
  m_TestSTD[0] = 0;
  m_TestSTD[1] = 1;
  m_TestSTD[2] = 2;
  m_MaxValueOfRGB = 256;
}

/* Destructor. */
template< typename TInputImage, typename TOutputImage >
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::
~VoronoiSegmentationRGBImageFilter()
{}

template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::SetMeanPercentError(double x[6])
{
  for ( unsigned int i = 0; i < 6; i++ )
    {
    m_MeanPercentError[i] = x[i];
    m_MeanTolerance[i] = std::fabs(x[i] * m_Mean[i]);
    }
}

template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::SetSTDPercentError(double x[6])
{
  for ( unsigned int i = 0; i < 6; i++ )
    {
    m_STDPercentError[i] = x[i];
    m_STDTolerance[i] = x[i] * m_STD[i];
    }
}

/* Initialization for the segmentation. */
template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >
::SetInput(unsigned int inputNumber, const InputImageType *input)
{
  this->Superclass::SetInput(inputNumber, input);
}

/* Initialization for the segmentation. */
template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >
::SetInput(const InputImageType *input)
{
  this->Superclass::SetInput(input);

  this->SetSize( this->GetInput()->GetLargestPossibleRegion().GetSize() );
  IndexType index;
  index.Fill(0);
  RegionType region;
  region.SetSize( this->GetSize() );
  region.SetIndex(index);

  m_WorkingImage = RGBHCVImage::New();
  m_WorkingImage->SetLargestPossibleRegion(region);
  m_WorkingImage->SetBufferedRegion(region);
  m_WorkingImage->SetRequestedRegion(region);
  m_WorkingImage->Allocate();

  itk::ImageRegionIteratorWithIndex< RGBHCVImage >         wit(m_WorkingImage, region);
  itk::ImageRegionConstIteratorWithIndex< InputImageType > iit(this->GetInput(), region);
  PixelType                                                ipixel;
  RGBHCVPixel                                              wpixel;

  double X;
  double Y;
  double Z;
  double L;
  double a;
  double b;
  double X0 = m_MaxValueOfRGB * 0.982;
  double Y0 = m_MaxValueOfRGB;
  double Z0 = m_MaxValueOfRGB * 1.183;

  while ( !iit.IsAtEnd() )
    {
    ipixel = iit.Get();
    wpixel[0] = ipixel[0];
    wpixel[1] = ipixel[1];
    wpixel[2] = ipixel[2];

    X =  0.607 * ipixel[0] + 0.174 * ipixel[1] + 0.201 * ipixel[2];
    Y =  0.299 * ipixel[0] + 0.587 * ipixel[1] + 0.114 * ipixel[2];
    Z =  0.066 * ipixel[1] + 1.117 * ipixel[2];
    X = std::pow( ( X / X0 ), 0.3333 );
    Y = std::pow( ( Y / Y0 ), 0.3333 );
    Z = std::pow( ( Z / Z0 ), 0.3333 );
    L = 116 * Y - 16;
    a = 500 * ( X - Y );
    b = 200 * ( Y - Z );

    if ( b != 0.0 )
      {
      wpixel[3] = std::atan2(b, a);     //H
      }
    else
      {
      wpixel[3] = 0;
      }
    wpixel[4] = std::sqrt(a * a + b * b); //C
    wpixel[5] = L;                       //V
    wit.Set(wpixel);
    ++wit;
    ++iit;
    }
}

template< typename TInputImage, typename TOutputImage >
bool
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::TestHomogeneity(IndexList & Plist)
{
  int         num = Plist.size();
  int         i, j;
  RGBHCVPixel getp;
  double      addp[6] = { 0, 0, 0, 0, 0, 0 };
  double      addpp[6] = { 0, 0, 0, 0, 0, 0 };

  for ( i = 0; i < num; i++ )
    {
    getp = m_WorkingImage->GetPixel(Plist[i]);
    for ( j = 0; j < 6; j++ )
      {
      addp[j] = addp[j] + getp[j];
      addpp[j] = addpp[j] + getp[j] * getp[j];
      }
    }

  double savemean[6], saveSTD[6];
  if ( num > 1 )
    {
    for ( i = 0; i < 6; i++ )
      {
      savemean[i] = addp[i] / num;
      saveSTD[i] = std::sqrt( ( addpp[i] - ( addp[i] * addp[i] ) / ( num ) ) / ( num - 1 ) );
      }
    }
  else
    {
    for ( i = 0; i < 6; i++ )
      {
      savemean[i] = 0;
      saveSTD[i] = -1;
      }
    }

  bool ok = 1;
  j = 0;
  double savem, savev;
  while ( ok && ( j < 3 ) )
    {
    savem = savemean[m_TestMean[j]] - m_Mean[m_TestMean[j]];
    savev = saveSTD[m_TestSTD[j]] - m_STD[m_TestSTD[j]];
    if ( ( savem < -m_MeanTolerance[m_TestMean[j]] )
         || ( savem > m_MeanTolerance[m_TestMean[j]] ) )
      {
      ok = 0;
      }
    if ( ( savev < -m_STDTolerance[m_TestSTD[j]] )
         || ( savev > m_STDTolerance[m_TestSTD[j]] ) )
      {
      ok = 0;
      }
    j++;
    }

  if ( ok )
    {
    return 1;
    }
  else
    {
    return 0;
    }
}

template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::TakeAPrior(const BinaryObjectImage *aprior)
{
  RegionType region = this->GetInput()->GetRequestedRegion();

  itk::ImageRegionConstIteratorWithIndex< BinaryObjectImage > ait(aprior, region);
  itk::ImageRegionIteratorWithIndex< RGBHCVImage >            iit(m_WorkingImage, region);

  unsigned int minx = 0, miny = 0, maxx = 0, maxy = 0;
  bool         status = 0;
  for ( unsigned int i = 0; i < this->GetSize()[1]; i++ )
    {
    for ( unsigned int j = 0; j < this->GetSize()[0]; j++ )
      {
      if ( ( status == 0 ) && ( ait.Get() ) )
        {
        miny = i;
        minx = j;
        maxy = i;
        maxx = j;
        status = 1;
        }
      else if ( ( status == 1 ) && ( ait.Get() ) )
        {
        maxy = i;
        if ( minx > j ) { minx = j; }
        if ( maxx < j ) { maxx = j; }
        }
      ++ait;
      }
    }

  int objnum = 0;
  int bkgnum = 0;

  float       objaddp[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
  float       objaddpp[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
  float       bkgaddp[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
  float       bkgaddpp[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
  RGBHCVPixel currp;

  ait.GoToBegin();
  iit.GoToBegin();
  unsigned int k;
  for ( unsigned int i = 0; i < miny; i++ )
    {
    for ( unsigned int j = 0; j < this->GetSize()[0]; j++ )
      {
      ++ait;
      ++iit;
      }
    }
  for ( unsigned int i = miny; i <= maxy; i++ )
    {
    for ( unsigned int j = 0; j < minx; j++ )
      {
      ++ait;
      ++iit;
      }
    for ( unsigned int j = minx; j <= maxx; j++ )
      {
      currp = iit.Get();
      if ( ait.Get() )
        {
        objnum++;
        for ( k = 0; k < 6; k++ )
          {
          objaddp[k] += currp[k];
          objaddpp[k] += currp[k] * currp[k];
          }
        }
      else
        {
        bkgnum++;
        for ( k = 0; k < 6; k++ )
          {
          bkgaddp[k] += currp[k];
          bkgaddpp[k] += currp[k] * currp[k];
          }
        }
      ++ait; ++iit;
      }
    for ( unsigned int j = maxx + 1; j < this->GetSize()[0]; j++ )
      {
      ++ait;
      ++iit;
      }
    }

  double b_Mean[6];
  double b_STD[6];
  float  diffMean[6];
  float  diffSTD[6];
  for ( unsigned int i = 0; i < 6; i++ )
    {
    m_Mean[i] = objaddp[i] / objnum;
    m_STD[i] = std::sqrt( ( objaddpp[i] - ( objaddp[i] * objaddp[i] ) / objnum ) / ( objnum - 1 ) );
    m_STDTolerance[i] = m_STD[i] * m_STDPercentError[i];
    if (bkgnum > 0)
      {
      b_Mean[i] = bkgaddp[i] / bkgnum;
      }
    if (bkgnum > 1)
      {
      b_STD[i] =
        std::sqrt( ( bkgaddpp[i] - ( bkgaddp[i] * bkgaddp[i] ) / bkgnum )
                   / ( bkgnum - 1 ) );
      }
    if (m_Mean[i] != 0.0)
      {
      diffMean[i] = ( b_Mean[i] - m_Mean[i] ) / m_Mean[i];
      }
    if ( diffMean[i] < 0 )
      {
      diffMean[i] = -diffMean[i];
      }
    if (m_STD[i] != 0.0)
      {
      diffSTD[i] = ( b_STD[i] - m_STD[i] ) / m_STD[i];
      }
    if ( diffSTD[i] < 0 )
      {
      diffSTD[i] = -diffSTD[i];
      }
    if ( this->GetUseBackgroundInAPrior() )
      {
      m_MeanTolerance[i] = diffMean[i] * m_Mean[i] * this->GetMeanDeviation();
      }
    else
      {
      m_MeanTolerance[i] = std::fabs(m_Mean[i] * m_MeanPercentError[i]);
      }
    }

  if ( objnum < 10 )
    {
/* a-prior doen's make too much sense */
    for ( unsigned int i = 0; i < 6; i++ )
      {
      m_MeanTolerance[i] = 0;
      m_STDTolerance[i] = 0;
      }
    }

/*  Sorting. */
  unsigned char tmp[6] = { 0, 1, 2, 3, 4, 5 };
  for ( unsigned j = 0; j < 3; j++ )
    {
    k = 0;
    for ( unsigned int i = 1; i < 6 - j; i++ )
      {
      if ( diffMean[tmp[i]] > diffMean[tmp[k]] )
        {
        k = i;
        }
      }
    m_TestMean[j] = tmp[k];
    tmp[k] = tmp[5 - j];
    }
  unsigned char tmp1[6] = { 0, 1, 2, 3, 4, 5 };
  for ( unsigned int j = 0; j < 3; j++ )
    {
    k = 0;
    for ( unsigned int i = 1; i < 6 - j; i++ )
      {
      if ( diffSTD[tmp1[i]] > diffSTD[tmp1[k]] )
        {
        k = i;
        }
      }
    m_TestSTD[j] = tmp1[k];
    tmp1[k] = tmp1[5 - j];
    }
}

template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
  os << indent << "MaxValueOfRGB: " << m_MaxValueOfRGB << std::endl;
  os << indent << "Mean: " << m_Mean << std::endl;
}
} //end namespace

#endif
<commit_msg>BUG: Uninitialized scalar field<commit_after>/*=========================================================================
 *
 *  Copyright Insight Software Consortium
 *
 *  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.txt
 *
 *  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.
 *
 *=========================================================================*/
#ifndef __itkVoronoiSegmentationRGBImageFilter_hxx
#define __itkVoronoiSegmentationRGBImageFilter_hxx
#include "itkVoronoiSegmentationRGBImageFilter.h"

#include "itkImageRegionIteratorWithIndex.h"
#include <cmath>

namespace itk
{
/* Constructor: setting of the default values for the parameters. */
template< typename TInputImage, typename TOutputImage >
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::VoronoiSegmentationRGBImageFilter()
{
  unsigned int i;

  for ( i = 0; i < 6; i++ )
    {
    m_Mean[i] = 0;
    m_STD[i] = 0;
    m_MeanTolerance[i] = 10;
    m_STDTolerance[i] = 10;
    m_MeanPercentError[i] = 0.10;
    m_STDPercentError[i] = 1.5;
    }
//testing RGB for both mean and STD. (default).
  m_TestMean[0] = 0;
  m_TestMean[1] = 1;
  m_TestMean[2] = 2;
  m_TestSTD[0] = 0;
  m_TestSTD[1] = 1;
  m_TestSTD[2] = 2;
  m_MaxValueOfRGB = 256;
}

/* Destructor. */
template< typename TInputImage, typename TOutputImage >
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::
~VoronoiSegmentationRGBImageFilter()
{}

template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::SetMeanPercentError(double x[6])
{
  for ( unsigned int i = 0; i < 6; i++ )
    {
    m_MeanPercentError[i] = x[i];
    m_MeanTolerance[i] = std::fabs(x[i] * m_Mean[i]);
    }
}

template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::SetSTDPercentError(double x[6])
{
  for ( unsigned int i = 0; i < 6; i++ )
    {
    m_STDPercentError[i] = x[i];
    m_STDTolerance[i] = x[i] * m_STD[i];
    }
}

/* Initialization for the segmentation. */
template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >
::SetInput(unsigned int inputNumber, const InputImageType *input)
{
  this->Superclass::SetInput(inputNumber, input);
}

/* Initialization for the segmentation. */
template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >
::SetInput(const InputImageType *input)
{
  this->Superclass::SetInput(input);

  this->SetSize( this->GetInput()->GetLargestPossibleRegion().GetSize() );
  IndexType index;
  index.Fill(0);
  RegionType region;
  region.SetSize( this->GetSize() );
  region.SetIndex(index);

  m_WorkingImage = RGBHCVImage::New();
  m_WorkingImage->SetLargestPossibleRegion(region);
  m_WorkingImage->SetBufferedRegion(region);
  m_WorkingImage->SetRequestedRegion(region);
  m_WorkingImage->Allocate();

  itk::ImageRegionIteratorWithIndex< RGBHCVImage >         wit(m_WorkingImage, region);
  itk::ImageRegionConstIteratorWithIndex< InputImageType > iit(this->GetInput(), region);
  PixelType                                                ipixel;
  RGBHCVPixel                                              wpixel;

  double X;
  double Y;
  double Z;
  double L;
  double a;
  double b;
  double X0 = m_MaxValueOfRGB * 0.982;
  double Y0 = m_MaxValueOfRGB;
  double Z0 = m_MaxValueOfRGB * 1.183;

  while ( !iit.IsAtEnd() )
    {
    ipixel = iit.Get();
    wpixel[0] = ipixel[0];
    wpixel[1] = ipixel[1];
    wpixel[2] = ipixel[2];

    X =  0.607 * ipixel[0] + 0.174 * ipixel[1] + 0.201 * ipixel[2];
    Y =  0.299 * ipixel[0] + 0.587 * ipixel[1] + 0.114 * ipixel[2];
    Z =  0.066 * ipixel[1] + 1.117 * ipixel[2];
    X = std::pow( ( X / X0 ), 0.3333 );
    Y = std::pow( ( Y / Y0 ), 0.3333 );
    Z = std::pow( ( Z / Z0 ), 0.3333 );
    L = 116 * Y - 16;
    a = 500 * ( X - Y );
    b = 200 * ( Y - Z );

    if ( b != 0.0 )
      {
      wpixel[3] = std::atan2(b, a);     //H
      }
    else
      {
      wpixel[3] = 0;
      }
    wpixel[4] = std::sqrt(a * a + b * b); //C
    wpixel[5] = L;                       //V
    wit.Set(wpixel);
    ++wit;
    ++iit;
    }
}

template< typename TInputImage, typename TOutputImage >
bool
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::TestHomogeneity(IndexList & Plist)
{
  int         num = Plist.size();
  int         i, j;
  RGBHCVPixel getp;
  double      addp[6] = { 0, 0, 0, 0, 0, 0 };
  double      addpp[6] = { 0, 0, 0, 0, 0, 0 };

  for ( i = 0; i < num; i++ )
    {
    getp = m_WorkingImage->GetPixel(Plist[i]);
    for ( j = 0; j < 6; j++ )
      {
      addp[j] = addp[j] + getp[j];
      addpp[j] = addpp[j] + getp[j] * getp[j];
      }
    }

  double savemean[6], saveSTD[6];
  if ( num > 1 )
    {
    for ( i = 0; i < 6; i++ )
      {
      savemean[i] = addp[i] / num;
      saveSTD[i] = std::sqrt( ( addpp[i] - ( addp[i] * addp[i] ) / ( num ) ) / ( num - 1 ) );
      }
    }
  else
    {
    for ( i = 0; i < 6; i++ )
      {
      savemean[i] = 0;
      saveSTD[i] = -1;
      }
    }

  bool ok = 1;
  j = 0;
  double savem, savev;
  while ( ok && ( j < 3 ) )
    {
    savem = savemean[m_TestMean[j]] - m_Mean[m_TestMean[j]];
    savev = saveSTD[m_TestSTD[j]] - m_STD[m_TestSTD[j]];
    if ( ( savem < -m_MeanTolerance[m_TestMean[j]] )
         || ( savem > m_MeanTolerance[m_TestMean[j]] ) )
      {
      ok = 0;
      }
    if ( ( savev < -m_STDTolerance[m_TestSTD[j]] )
         || ( savev > m_STDTolerance[m_TestSTD[j]] ) )
      {
      ok = 0;
      }
    j++;
    }

  if ( ok )
    {
    return 1;
    }
  else
    {
    return 0;
    }
}

template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >::TakeAPrior(const BinaryObjectImage *aprior)
{
  RegionType region = this->GetInput()->GetRequestedRegion();

  itk::ImageRegionConstIteratorWithIndex< BinaryObjectImage > ait(aprior, region);
  itk::ImageRegionIteratorWithIndex< RGBHCVImage >            iit(m_WorkingImage, region);

  unsigned int minx = 0, miny = 0, maxx = 0, maxy = 0;
  bool         status = 0;
  for ( unsigned int i = 0; i < this->GetSize()[1]; i++ )
    {
    for ( unsigned int j = 0; j < this->GetSize()[0]; j++ )
      {
      if ( ( status == 0 ) && ( ait.Get() ) )
        {
        miny = i;
        minx = j;
        maxy = i;
        maxx = j;
        status = 1;
        }
      else if ( ( status == 1 ) && ( ait.Get() ) )
        {
        maxy = i;
        if ( minx > j ) { minx = j; }
        if ( maxx < j ) { maxx = j; }
        }
      ++ait;
      }
    }

  int objnum = 0;
  int bkgnum = 0;

  float       objaddp[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
  float       objaddpp[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
  float       bkgaddp[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
  float       bkgaddpp[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
  RGBHCVPixel currp;

  ait.GoToBegin();
  iit.GoToBegin();
  unsigned int k;
  for ( unsigned int i = 0; i < miny; i++ )
    {
    for ( unsigned int j = 0; j < this->GetSize()[0]; j++ )
      {
      ++ait;
      ++iit;
      }
    }
  for ( unsigned int i = miny; i <= maxy; i++ )
    {
    for ( unsigned int j = 0; j < minx; j++ )
      {
      ++ait;
      ++iit;
      }
    for ( unsigned int j = minx; j <= maxx; j++ )
      {
      currp = iit.Get();
      if ( ait.Get() )
        {
        objnum++;
        for ( k = 0; k < 6; k++ )
          {
          objaddp[k] += currp[k];
          objaddpp[k] += currp[k] * currp[k];
          }
        }
      else
        {
        bkgnum++;
        for ( k = 0; k < 6; k++ )
          {
          bkgaddp[k] += currp[k];
          bkgaddpp[k] += currp[k] * currp[k];
          }
        }
      ++ait; ++iit;
      }
    for ( unsigned int j = maxx + 1; j < this->GetSize()[0]; j++ )
      {
      ++ait;
      ++iit;
      }
    }

  double b_Mean[6];
  double b_STD[6];
  float  diffMean[6];
  float  diffSTD[6];
  for ( unsigned int i = 0; i < 6; i++ )
    {
    m_Mean[i] = objaddp[i] / objnum;
    m_STD[i] = std::sqrt( ( objaddpp[i] - ( objaddp[i] * objaddp[i] ) / objnum ) / ( objnum - 1 ) );
    m_STDTolerance[i] = m_STD[i] * m_STDPercentError[i];
    if (bkgnum > 0)
      {
      b_Mean[i] = bkgaddp[i] / bkgnum;
      }
    else
      {
      b_Mean[i] = 0.0;
      }
    if (bkgnum > 1)
      {
      b_STD[i] =
        std::sqrt( ( bkgaddpp[i] - ( bkgaddp[i] * bkgaddp[i] ) / bkgnum )
                   / ( bkgnum - 1 ) );
      }
    else
      {
      b_STD[i] = 0.0;
      }
    if (m_Mean[i] != 0.0)
      {
      diffMean[i] = ( b_Mean[i] - m_Mean[i] ) / m_Mean[i];
      }
    else
      {
      diffMean[i] = 0.0;
      }
    if ( diffMean[i] < 0 )
      {
      diffMean[i] = -diffMean[i];
      }
    if (m_STD[i] != 0.0)
      {
      diffSTD[i] = ( b_STD[i] - m_STD[i] ) / m_STD[i];
      }
    else
      {
      diffSTD[i] = 0.0;
      }
    if ( diffSTD[i] < 0 )
      {
      diffSTD[i] = -diffSTD[i];
      }
    if ( this->GetUseBackgroundInAPrior() )
      {
      m_MeanTolerance[i] = diffMean[i] * m_Mean[i] * this->GetMeanDeviation();
      }
    else
      {
      m_MeanTolerance[i] = std::fabs(m_Mean[i] * m_MeanPercentError[i]);
      }
    }

  if ( objnum < 10 )
    {
/* a-prior doen's make too much sense */
    for ( unsigned int i = 0; i < 6; i++ )
      {
      m_MeanTolerance[i] = 0;
      m_STDTolerance[i] = 0;
      }
    }

/*  Sorting. */
  unsigned char tmp[6] = { 0, 1, 2, 3, 4, 5 };
  for ( unsigned j = 0; j < 3; j++ )
    {
    k = 0;
    for ( unsigned int i = 1; i < 6 - j; i++ )
      {
      if ( diffMean[tmp[i]] > diffMean[tmp[k]] )
        {
        k = i;
        }
      }
    m_TestMean[j] = tmp[k];
    tmp[k] = tmp[5 - j];
    }
  unsigned char tmp1[6] = { 0, 1, 2, 3, 4, 5 };
  for ( unsigned int j = 0; j < 3; j++ )
    {
    k = 0;
    for ( unsigned int i = 1; i < 6 - j; i++ )
      {
      if ( diffSTD[tmp1[i]] > diffSTD[tmp1[k]] )
        {
        k = i;
        }
      }
    m_TestSTD[j] = tmp1[k];
    tmp1[k] = tmp1[5 - j];
    }
}

template< typename TInputImage, typename TOutputImage >
void
VoronoiSegmentationRGBImageFilter< TInputImage, TOutputImage >
::PrintSelf(std::ostream & os, Indent indent) const
{
  Superclass::PrintSelf(os, indent);
  os << indent << "MaxValueOfRGB: " << m_MaxValueOfRGB << std::endl;
  os << indent << "Mean: " << m_Mean << std::endl;
}
} //end namespace

#endif
<|endoftext|>


<commit_before>//
//  main.cpp
//  GLEngineExample1
//
//  Created by Asger Nyman Christiansen on 18/12/2016.
//  Copyright © 2016 Asger Nyman Christiansen. All rights reserved.
//

#include "GLCamera.h"
#include "MeshCreator.h"
#include "materials/GLColorMaterial.h"
#include "gtx/rotate_vector.hpp"
#include "GLAmbientOcclusionEffect.h"

#define SDL_MAIN_HANDLED
#include "SDL.h"

using namespace std;
using namespace glm;
using namespace gle;
using namespace mesh;

shared_ptr<float> cube_rotation_angle = make_shared<float>(0.f);

void print_fps(double elapsedTime)
{
    static int draws = 0;
    draws++;
    static float seconds = 0.;
    seconds += elapsedTime;
    if(seconds > 5)
    {
        std::cout << "FPS: " << ((float)draws)/seconds << std::endl;
        seconds = 0.;
        draws = 0;
    }
}

void update(GLCamera& camera)
{
    static float last_time = time();
    float current_time = time();
    float elapsed_time = current_time - last_time;
    last_time = current_time;

    print_fps(elapsed_time);
    *cube_rotation_angle = current_time;

    static vec3 view_position = vec3(0., 0., 5.);
    static vec3 view_direction = vec3(0., 0., -1.);
    const float speed = 3.;

    const Uint8* currentKeyStates = SDL_GetKeyboardState( NULL );

    if(currentKeyStates[ SDL_SCANCODE_S ])
    {
        view_position -= speed * elapsed_time * view_direction;
    }
    else if(currentKeyStates[ SDL_SCANCODE_W ])
    {
        view_position += speed * elapsed_time * view_direction;
    }

    auto side = normalize(cross(view_direction, vec3(0.,1.,0.)));
    auto up = normalize(cross(side, view_direction));
    if(currentKeyStates[ SDL_SCANCODE_A ])
    {
        view_direction = vec3(glm::rotate(mat4(), elapsed_time, up) * vec4(view_direction, 1.));
    }
    else if(currentKeyStates[ SDL_SCANCODE_D ])
    {
        view_direction = vec3(glm::rotate(mat4(), -elapsed_time, up) * vec4(view_direction, 1.));
    }
    else if(currentKeyStates[ SDL_SCANCODE_E ])
    {
        view_direction = vec3(glm::rotate(mat4(), -elapsed_time, side) * vec4(view_direction, 1.));
    }
    else if(currentKeyStates[ SDL_SCANCODE_Q ])
    {
        view_direction = vec3(glm::rotate(mat4(), elapsed_time, side) * vec4(view_direction, 1.));
    }
    camera.set_view(view_position, view_direction);
}

void create_cube(GLScene& root)
{
    auto material = make_shared<GLColorMaterial>(vec3(0.5, 0.1, 0.7));
    auto geometry = MeshCreator::create_box(false);

    auto rotation_node = std::make_shared<GLRotationNode>(vec3(1., 1., 0.), cube_rotation_angle);

    root.add_child(rotation_node)->add_leaf(geometry, material);
}

void create_room(GLScene& root)
{
    auto color_material = make_shared<GLColorMaterial>(vec3(0.5, 0.5, 0.5));
    auto box = MeshCreator::create_box(true);
    auto scale_node = std::make_shared<GLTransformationNode>(scale(vec3(10., 10., 10.)));
    root.add_child(scale_node)->add_leaf(box, color_material);
}

int main(int argc, const char * argv[])
{
    // Initialize SDL
    if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
        throw std::runtime_error("SDL init failed");
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

    // Create window
    int window_width = 1200;
    int window_height = 700;
    auto window = SDL_CreateWindow( "Shadows", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE );
    if( window == NULL )
    {
        printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
        throw std::runtime_error("SDL init failed");
    }

    // Create context
    auto glcontext = SDL_GL_CreateContext(window);

    // Create camera
    auto camera = GLCamera(window_width, window_height);

    // Create scene
    auto scene = GLScene();
    create_room(scene);
    create_cube(scene);

    auto point_light = make_shared<GLPointLight>();
    scene.add_light(point_light);
    scene.add_light(std::make_shared<GLDirectionalLight>(glm::vec3(1., -1., 0.)));

    // Create post effect
    auto ssao = GLAmbientOcclusionEffect();

    // run while the window is open
    bool quit = false;
    while(!quit)
    {
        // process pending events
        SDL_Event e;
        while( SDL_PollEvent( &e ) != 0 )
        {
            if( e.type == SDL_QUIT || e.key.keysym.sym == SDLK_ESCAPE)
            {
                quit = true;
            }
        }

        // update the scene based on the time elapsed since last update
        update(camera);
        point_light->position = vec3(3. * sin(gle::time()), 5. * cos(gle::time()), 1.);

        // draw one frame
        camera.draw(scene);
        camera.apply_post_effect(ssao);

        SDL_GL_SwapWindow(window);
    }

    // Delete context
    SDL_GL_DeleteContext(glcontext);

    // Destroy window
    SDL_DestroyWindow( window );
    window = NULL;

    // Quit SDL subsystems
    SDL_Quit();
    return 0;
}
<commit_msg>Added point light object.<commit_after>//
//  main.cpp
//  GLEngineExample1
//
//  Created by Asger Nyman Christiansen on 18/12/2016.
//  Copyright © 2016 Asger Nyman Christiansen. All rights reserved.
//

#include "GLCamera.h"
#include "MeshCreator.h"
#include "materials/GLColorMaterial.h"
#include "gtx/rotate_vector.hpp"
#include "GLAmbientOcclusionEffect.h"

#define SDL_MAIN_HANDLED
#include "SDL.h"

using namespace std;
using namespace glm;
using namespace gle;
using namespace mesh;

shared_ptr<float> cube_rotation_angle = make_shared<float>(0.f);

void print_fps(double elapsedTime)
{
    static int draws = 0;
    draws++;
    static float seconds = 0.;
    seconds += elapsedTime;
    if(seconds > 5)
    {
        std::cout << "FPS: " << ((float)draws)/seconds << std::endl;
        seconds = 0.;
        draws = 0;
    }
}

void update(GLCamera& camera)
{
    static float last_time = time();
    float current_time = time();
    float elapsed_time = current_time - last_time;
    last_time = current_time;

    print_fps(elapsed_time);
    *cube_rotation_angle = current_time;

    static vec3 view_position = vec3(0., 0., 5.);
    static vec3 view_direction = vec3(0., 0., -1.);
    const float speed = 3.;

    const Uint8* currentKeyStates = SDL_GetKeyboardState( NULL );

    if(currentKeyStates[ SDL_SCANCODE_S ])
    {
        view_position -= speed * elapsed_time * view_direction;
    }
    else if(currentKeyStates[ SDL_SCANCODE_W ])
    {
        view_position += speed * elapsed_time * view_direction;
    }

    auto side = normalize(cross(view_direction, vec3(0.,1.,0.)));
    auto up = normalize(cross(side, view_direction));
    if(currentKeyStates[ SDL_SCANCODE_A ])
    {
        view_direction = vec3(glm::rotate(mat4(), elapsed_time, up) * vec4(view_direction, 1.));
    }
    else if(currentKeyStates[ SDL_SCANCODE_D ])
    {
        view_direction = vec3(glm::rotate(mat4(), -elapsed_time, up) * vec4(view_direction, 1.));
    }
    else if(currentKeyStates[ SDL_SCANCODE_E ])
    {
        view_direction = vec3(glm::rotate(mat4(), -elapsed_time, side) * vec4(view_direction, 1.));
    }
    else if(currentKeyStates[ SDL_SCANCODE_Q ])
    {
        view_direction = vec3(glm::rotate(mat4(), elapsed_time, side) * vec4(view_direction, 1.));
    }
    camera.set_view(view_position, view_direction);
}

void create_cube(GLScene& root)
{
    auto material = make_shared<GLColorMaterial>(vec3(0.5, 0.1, 0.7));
    auto geometry = MeshCreator::create_box(false);

    auto rotation_node = std::make_shared<GLRotationNode>(vec3(1., 1., 0.), cube_rotation_angle);

    root.add_child(rotation_node)->add_leaf(geometry, material);
}

void create_room(GLScene& root)
{
    auto color_material = make_shared<GLColorMaterial>(vec3(0.5, 0.5, 0.5));
    auto box = MeshCreator::create_box(true);
    auto scale_node = std::make_shared<GLTransformationNode>(scale(vec3(10., 10., 10.)));
    root.add_child(scale_node)->add_leaf(box, color_material);
}

int main(int argc, const char * argv[])
{
    // Initialize SDL
    if( SDL_Init( SDL_INIT_EVERYTHING ) < 0 )
    {
        printf( "SDL could not initialize! SDL_Error: %s\n", SDL_GetError() );
        throw std::runtime_error("SDL init failed");
    }

    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
    SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);

    // Create window
    int window_width = 1200;
    int window_height = 700;
    auto window = SDL_CreateWindow( "Shadows", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, window_width, window_height, SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE );
    if( window == NULL )
    {
        printf( "Window could not be created! SDL_Error: %s\n", SDL_GetError() );
        throw std::runtime_error("SDL init failed");
    }

    // Create context
    auto glcontext = SDL_GL_CreateContext(window);

    // Create camera
    auto camera = GLCamera(window_width, window_height);

    // Create scene
    auto scene = GLScene();
    create_room(scene);
    create_cube(scene);

    // Light
    auto material = make_shared<GLColorMaterial>(vec3(1., 1., 1.));
    auto geometry = MeshCreator::create_box(false);
    auto light_translation = make_shared<vec3>(0., 0., 0.);
    scene.add_child(std::make_shared<GLTranslationNode>(light_translation))->add_child(make_shared<GLTransformationNode>(scale(vec3(0.1, 0.1, 0.1))))->add_leaf(geometry, material);

    auto point_light = make_shared<GLPointLight>();
    scene.add_light(point_light);
    scene.add_light(std::make_shared<GLDirectionalLight>(glm::vec3(1., -1., 0.)));

    // Create post effect
    auto ssao = GLAmbientOcclusionEffect();

    // run while the window is open
    bool quit = false;
    while(!quit)
    {
        // process pending events
        SDL_Event e;
        while( SDL_PollEvent( &e ) != 0 )
        {
            if( e.type == SDL_QUIT || e.key.keysym.sym == SDLK_ESCAPE)
            {
                quit = true;
            }
        }

        // update the scene based on the time elapsed since last update
        update(camera);
        point_light->position = vec3(3. * sin(gle::time()), 5. * cos(gle::time()), 0.);
        *light_translation = point_light->position * 1.1f;

        // draw one frame
        camera.draw(scene);
        camera.apply_post_effect(ssao);

        SDL_GL_SwapWindow(window);
    }

    // Delete context
    SDL_GL_DeleteContext(glcontext);

    // Destroy window
    SDL_DestroyWindow( window );
    window = NULL;

    // Quit SDL subsystems
    SDL_Quit();
    return 0;
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 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 "chrome/browser/chromeos/cros/language_library.h"

#include "base/basictypes.h"
#include "base/message_loop.h"
#include "base/string_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "third_party/cros/chromeos_keyboard.h"
#include "third_party/icu/public/common/unicode/uloc.h"

// Allows InvokeLater without adding refcounting. This class is a Singleton and
// won't be deleted until it's last InvokeLater is run.
template <>
struct RunnableMethodTraits<chromeos::LanguageLibraryImpl> {
  void RetainCallee(chromeos::LanguageLibraryImpl* obj) {}
  void ReleaseCallee(chromeos::LanguageLibraryImpl* obj) {}
};

namespace {

// Finds a property which has |new_prop.key| from |prop_list|, and replaces the
// property with |new_prop|. Returns true if such a property is found.
bool FindAndUpdateProperty(const chromeos::ImeProperty& new_prop,
                           chromeos::ImePropertyList* prop_list) {
  for (size_t i = 0; i < prop_list->size(); ++i) {
    chromeos::ImeProperty& prop = prop_list->at(i);
    if (prop.key == new_prop.key) {
      const int saved_id = prop.selection_item_id;
      // Update the list except the radio id. As written in chromeos_language.h,
      // |prop.selection_item_id| is dummy.
      prop = new_prop;
      prop.selection_item_id = saved_id;
      return true;
    }
  }
  return false;
}

// There are some differences between ISO 639-2 (T) and ISO 639-2 B, and
// some language codes are not recognized by ICU (i.e. ICU cannot convert
// these codes to two-letter language codes and display names). Hence we
// convert these codes to ones that ICU recognize.
//
// See http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes for details.
const char* kIso639VariantMapping[][2] = {
  {"cze", "ces"},
  {"ger", "deu"},
  {"gre", "ell"},
  // "scr" is not a ISO 639 code. For some reason, evdev.xml uses "scr" as
  // the language code for Croatian.
  {"scr", "hrv"},
  {"rum", "ron"},
  {"slo", "slk"},
};

// The default keyboard layout.
const char kDefaultKeyboardLayout[] = "us";
}  // namespace

namespace chromeos {

std::string LanguageLibrary::NormalizeLanguageCode(
    const std::string& language_code) {
  // Some ibus engines return locale codes like "zh_CN" as language codes.
  // Normalize these to like "zh-CN".
  if (language_code.size() >= 5 && language_code[2] == '_') {
    std::string copied_language_code = language_code;
    copied_language_code[2] = '-';
    // Downcase the language code part.
    for (size_t i = 0; i < 2; ++i) {
      copied_language_code[i] = ToLowerASCII(copied_language_code[i]);
    }
    // Upcase the country code part.
    for (size_t i = 3; i < copied_language_code.size(); ++i) {
      copied_language_code[i] = ToUpperASCII(copied_language_code[i]);
    }
    return copied_language_code;
  }
  // We only handle three-letter codes from here.
  if (language_code.size() != 3) {
    return language_code;
  }

  // Convert special language codes. See comments at kIso639VariantMapping.
  std::string copied_language_code = language_code;
  for (size_t i = 0; i < arraysize(kIso639VariantMapping); ++i) {
    if (language_code == kIso639VariantMapping[i][0]) {
      copied_language_code = kIso639VariantMapping[i][1];
    }
  }
  // Convert the three-letter code to two letter-code.
  UErrorCode error = U_ZERO_ERROR;
  char two_letter_code[ULOC_LANG_CAPACITY];
  uloc_getLanguage(copied_language_code.c_str(),
                   two_letter_code, sizeof(two_letter_code), &error);
  if (U_FAILURE(error)) {
    return language_code;
  }
  return two_letter_code;
}

bool LanguageLibrary::IsKeyboardLayout(
    const std::string& input_method_id) {
  const bool kCaseInsensitive = false;
  return StartsWithASCII(input_method_id, "xkb:", kCaseInsensitive);
}

std::string LanguageLibrary::GetLanguageCodeFromDescriptor(
    const InputMethodDescriptor& descriptor) {
  // Special-case Chewing. Handle this as zh-TW, rather than zh.
  if (descriptor.id == "chewing" &&
      descriptor.language_code == "zh") {
    return "zh-TW";
  }

  std::string language_code =
      LanguageLibrary::NormalizeLanguageCode(descriptor.language_code);

  // Add country codes to language codes of some XKB input methods to make
  // these compatible with Chrome's application locale codes like "en-US".
  // TODO(satorux): Maybe we need to handle "es" for "es-419".
  if (IsKeyboardLayout(descriptor.id) &&
      (language_code == "en" ||
       language_code == "zh" ||
       language_code == "pt")) {
    std::vector<std::string> portions;
    SplitString(descriptor.id, ':', &portions);
    if (portions.size() >= 2 && !portions[1].empty()) {
      language_code.append("-");
      language_code.append(StringToUpperASCII(portions[1]));
    }
  }
  return language_code;
}

std::string LanguageLibrary::GetKeyboardLayoutName(
    const std::string& input_method_id) {
  std::vector<std::string> portions;
  SplitString(input_method_id, ':', &portions);
  if (portions.size() > 1 && !portions[1].empty()) {
    std::string keyboard_layout = portions[1];
    if (portions.size() > 2 && !portions[2].empty()) {
      keyboard_layout.append("(");
      keyboard_layout.append(portions[2]);
      keyboard_layout.append(")");
    }
    return keyboard_layout;
  }
  return kDefaultKeyboardLayout;
}

LanguageLibraryImpl::LanguageLibraryImpl()
    : input_method_status_connection_(NULL),
      current_input_method_("", "", ""),
      is_focused_(false) {
  scoped_ptr<InputMethodDescriptors> input_method_descriptors(
      CreateFallbackInputMethodDescriptors());
  current_input_method_ = input_method_descriptors->at(0);
}

LanguageLibraryImpl::~LanguageLibraryImpl() {
  if (input_method_status_connection_) {
    chromeos::DisconnectInputMethodStatus(input_method_status_connection_);
  }
}

LanguageLibraryImpl::Observer::~Observer() {
}

void LanguageLibraryImpl::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void LanguageLibraryImpl::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

chromeos::InputMethodDescriptors* LanguageLibraryImpl::GetActiveInputMethods() {
  chromeos::InputMethodDescriptors* result = NULL;
  if (EnsureLoadedAndStarted()) {
    result = chromeos::GetActiveInputMethods(input_method_status_connection_);
  }
  if (!result || result->empty()) {
    result = CreateFallbackInputMethodDescriptors();
  }
  return result;
}

chromeos::InputMethodDescriptors*
LanguageLibraryImpl::GetSupportedInputMethods() {
  chromeos::InputMethodDescriptors* result = NULL;
  if (EnsureLoadedAndStarted()) {
    result = chromeos::GetSupportedInputMethods(
        input_method_status_connection_);
  }
  if (!result || result->empty()) {
    result = CreateFallbackInputMethodDescriptors();
  }
  return result;
}

void LanguageLibraryImpl::ChangeInputMethod(
    const std::string& input_method_id) {
  if (EnsureLoadedAndStarted()) {
    chromeos::ChangeInputMethod(
        input_method_status_connection_, input_method_id.c_str());
  }
}

void LanguageLibraryImpl::SetImePropertyActivated(const std::string& key,
                                                  bool activated) {
  DCHECK(!key.empty());
  if (EnsureLoadedAndStarted()) {
    chromeos::SetImePropertyActivated(
        input_method_status_connection_, key.c_str(), activated);
  }
}

bool LanguageLibraryImpl::InputMethodIsActivated(
    const std::string& input_method_id) {
  scoped_ptr<InputMethodDescriptors> active_input_method_descriptors(
      CrosLibrary::Get()->GetLanguageLibrary()->GetActiveInputMethods());
  for (size_t i = 0; i < active_input_method_descriptors->size(); ++i) {
    if (active_input_method_descriptors->at(i).id == input_method_id) {
      return true;
    }
  }
  return false;
}

bool LanguageLibraryImpl::GetImeConfig(
    const char* section, const char* config_name, ImeConfigValue* out_value) {
  bool success = false;
  if (EnsureLoadedAndStarted()) {
    success = chromeos::GetImeConfig(
        input_method_status_connection_, section, config_name, out_value);
  }
  return success;
}

bool LanguageLibraryImpl::SetImeConfig(
    const char* section, const char* config_name, const ImeConfigValue& value) {
  const ConfigKeyType key = std::make_pair(section, config_name);
  pending_config_requests_.erase(key);
  pending_config_requests_.insert(std::make_pair(key, value));
  FlushImeConfig();
  return pending_config_requests_.empty();
}

void LanguageLibraryImpl::FlushImeConfig() {
  if (EnsureLoadedAndStarted()) {
    LOG(INFO) << "Sending " << pending_config_requests_.size()
              << " set config command(s)";
    InputMethodConfigRequests::iterator iter = pending_config_requests_.begin();
    while (iter != pending_config_requests_.end()) {
      const std::string& section = iter->first.first;
      const std::string& config_name = iter->first.second;
      const ImeConfigValue& value = iter->second;
      if (chromeos::SetImeConfig(input_method_status_connection_,
                                 section.c_str(), config_name.c_str(), value)) {
        // Successfully sent. Remove the command and proceed to the next one.
        pending_config_requests_.erase(iter++);
      } else {
        LOG(ERROR) << "chromeos::SetImeConfig failed. Will retry later: "
                   << section << "/" << config_name;
        ++iter;  // Do not remove the command.
      }
    }
    if (pending_config_requests_.empty()) {
      timer_.Stop();  // no-op if it's not running.
    }
  } else {
    LOG(INFO) << "No connection to IBus. # of pending set config commands: "
              << pending_config_requests_.size();
    if (!timer_.IsRunning()) {
      static const int64 kTimerIntervalInSec = 1;
      timer_.Start(base::TimeDelta::FromSeconds(kTimerIntervalInSec), this,
                   &LanguageLibraryImpl::FlushImeConfig);
    }
  }
}

// static
void LanguageLibraryImpl::InputMethodChangedHandler(
    void* object, const chromeos::InputMethodDescriptor& current_input_method) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->UpdateCurrentInputMethod(current_input_method);
}

// static
void LanguageLibraryImpl::RegisterPropertiesHandler(
    void* object, const ImePropertyList& prop_list) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->RegisterProperties(prop_list);
}

// static
void LanguageLibraryImpl::UpdatePropertyHandler(
    void* object, const ImePropertyList& prop_list) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->UpdateProperty(prop_list);
}

// static
void LanguageLibraryImpl::FocusChangedHandler(void* object, bool is_focused) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->FocusChanged(is_focused);
}

bool LanguageLibraryImpl::EnsureStarted() {
  if (input_method_status_connection_) {
    if (chromeos::InputMethodStatusConnectionIsAlive(
            input_method_status_connection_)) {
      return true;
    }
    DLOG(WARNING) << "IBus connection is closed. Trying to reconnect...";
    chromeos::DisconnectInputMethodStatus(input_method_status_connection_);
  }
  input_method_status_connection_ = chromeos::MonitorInputMethodStatus(
      this,
      &InputMethodChangedHandler,
      &RegisterPropertiesHandler,
      &UpdatePropertyHandler,
      &FocusChangedHandler);
  return input_method_status_connection_ != NULL;
}

bool LanguageLibraryImpl::EnsureLoadedAndStarted() {
  return CrosLibrary::Get()->EnsureLoaded() &&
         EnsureStarted();
}

void LanguageLibraryImpl::UpdateCurrentInputMethod(
    const chromeos::InputMethodDescriptor& current_input_method) {
  // Make sure we run on UI thread.
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    DLOG(INFO) << "UpdateCurrentInputMethod (Background thread)";
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        // NewRunnableMethod() copies |current_input_method| by value.
        NewRunnableMethod(
            this, &LanguageLibraryImpl::UpdateCurrentInputMethod,
            current_input_method));
    return;
  }

  DLOG(INFO) << "UpdateCurrentInputMethod (UI thread)";
  if (IsKeyboardLayout(current_input_method.id)) {
    // If the new input method is a keyboard layout, switch the keyboard.
    chromeos::SetCurrentKeyboardLayoutByName(
        GetKeyboardLayoutName(current_input_method.id));
  } else {
    // If the new input method is an IME, change the keyboard back to the
    // default layout (US).  TODO(satorux): What if the user is using a non-US
    // keyboard, such as a Japanese keyboard? We need to rework this.
    chromeos::SetCurrentKeyboardLayoutByName(kDefaultKeyboardLayout);
  }

  current_input_method_ = current_input_method;
  FOR_EACH_OBSERVER(Observer, observers_, InputMethodChanged(this));
}

void LanguageLibraryImpl::RegisterProperties(const ImePropertyList& prop_list) {
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableMethod(
            this, &LanguageLibraryImpl::RegisterProperties, prop_list));
    return;
  }

  // |prop_list| might be empty. This means "clear all properties."
  current_ime_properties_ = prop_list;
  FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
}

void LanguageLibraryImpl::UpdateProperty(const ImePropertyList& prop_list) {
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableMethod(
            this, &LanguageLibraryImpl::UpdateProperty, prop_list));
    return;
  }

  for (size_t i = 0; i < prop_list.size(); ++i) {
    FindAndUpdateProperty(prop_list[i], &current_ime_properties_);
  }
  FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
}

void LanguageLibraryImpl::FocusChanged(bool is_focused) {
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableMethod(
            this, &LanguageLibraryImpl::FocusChanged, is_focused));
    return;
  }

  is_focused_ = is_focused;
  FOR_EACH_OBSERVER(Observer, observers_, FocusChanged(this));
}

}  // namespace chromeos
<commit_msg>Remove the too chatty LOG(INFO):<commit_after>// Copyright (c) 2009 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 "chrome/browser/chromeos/cros/language_library.h"

#include "base/basictypes.h"
#include "base/message_loop.h"
#include "base/string_util.h"
#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/chromeos/cros/cros_library.h"
#include "third_party/cros/chromeos_keyboard.h"
#include "third_party/icu/public/common/unicode/uloc.h"

// Allows InvokeLater without adding refcounting. This class is a Singleton and
// won't be deleted until it's last InvokeLater is run.
template <>
struct RunnableMethodTraits<chromeos::LanguageLibraryImpl> {
  void RetainCallee(chromeos::LanguageLibraryImpl* obj) {}
  void ReleaseCallee(chromeos::LanguageLibraryImpl* obj) {}
};

namespace {

// Finds a property which has |new_prop.key| from |prop_list|, and replaces the
// property with |new_prop|. Returns true if such a property is found.
bool FindAndUpdateProperty(const chromeos::ImeProperty& new_prop,
                           chromeos::ImePropertyList* prop_list) {
  for (size_t i = 0; i < prop_list->size(); ++i) {
    chromeos::ImeProperty& prop = prop_list->at(i);
    if (prop.key == new_prop.key) {
      const int saved_id = prop.selection_item_id;
      // Update the list except the radio id. As written in chromeos_language.h,
      // |prop.selection_item_id| is dummy.
      prop = new_prop;
      prop.selection_item_id = saved_id;
      return true;
    }
  }
  return false;
}

// There are some differences between ISO 639-2 (T) and ISO 639-2 B, and
// some language codes are not recognized by ICU (i.e. ICU cannot convert
// these codes to two-letter language codes and display names). Hence we
// convert these codes to ones that ICU recognize.
//
// See http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes for details.
const char* kIso639VariantMapping[][2] = {
  {"cze", "ces"},
  {"ger", "deu"},
  {"gre", "ell"},
  // "scr" is not a ISO 639 code. For some reason, evdev.xml uses "scr" as
  // the language code for Croatian.
  {"scr", "hrv"},
  {"rum", "ron"},
  {"slo", "slk"},
};

// The default keyboard layout.
const char kDefaultKeyboardLayout[] = "us";
}  // namespace

namespace chromeos {

std::string LanguageLibrary::NormalizeLanguageCode(
    const std::string& language_code) {
  // Some ibus engines return locale codes like "zh_CN" as language codes.
  // Normalize these to like "zh-CN".
  if (language_code.size() >= 5 && language_code[2] == '_') {
    std::string copied_language_code = language_code;
    copied_language_code[2] = '-';
    // Downcase the language code part.
    for (size_t i = 0; i < 2; ++i) {
      copied_language_code[i] = ToLowerASCII(copied_language_code[i]);
    }
    // Upcase the country code part.
    for (size_t i = 3; i < copied_language_code.size(); ++i) {
      copied_language_code[i] = ToUpperASCII(copied_language_code[i]);
    }
    return copied_language_code;
  }
  // We only handle three-letter codes from here.
  if (language_code.size() != 3) {
    return language_code;
  }

  // Convert special language codes. See comments at kIso639VariantMapping.
  std::string copied_language_code = language_code;
  for (size_t i = 0; i < arraysize(kIso639VariantMapping); ++i) {
    if (language_code == kIso639VariantMapping[i][0]) {
      copied_language_code = kIso639VariantMapping[i][1];
    }
  }
  // Convert the three-letter code to two letter-code.
  UErrorCode error = U_ZERO_ERROR;
  char two_letter_code[ULOC_LANG_CAPACITY];
  uloc_getLanguage(copied_language_code.c_str(),
                   two_letter_code, sizeof(two_letter_code), &error);
  if (U_FAILURE(error)) {
    return language_code;
  }
  return two_letter_code;
}

bool LanguageLibrary::IsKeyboardLayout(
    const std::string& input_method_id) {
  const bool kCaseInsensitive = false;
  return StartsWithASCII(input_method_id, "xkb:", kCaseInsensitive);
}

std::string LanguageLibrary::GetLanguageCodeFromDescriptor(
    const InputMethodDescriptor& descriptor) {
  // Special-case Chewing. Handle this as zh-TW, rather than zh.
  if (descriptor.id == "chewing" &&
      descriptor.language_code == "zh") {
    return "zh-TW";
  }

  std::string language_code =
      LanguageLibrary::NormalizeLanguageCode(descriptor.language_code);

  // Add country codes to language codes of some XKB input methods to make
  // these compatible with Chrome's application locale codes like "en-US".
  // TODO(satorux): Maybe we need to handle "es" for "es-419".
  if (IsKeyboardLayout(descriptor.id) &&
      (language_code == "en" ||
       language_code == "zh" ||
       language_code == "pt")) {
    std::vector<std::string> portions;
    SplitString(descriptor.id, ':', &portions);
    if (portions.size() >= 2 && !portions[1].empty()) {
      language_code.append("-");
      language_code.append(StringToUpperASCII(portions[1]));
    }
  }
  return language_code;
}

std::string LanguageLibrary::GetKeyboardLayoutName(
    const std::string& input_method_id) {
  std::vector<std::string> portions;
  SplitString(input_method_id, ':', &portions);
  if (portions.size() > 1 && !portions[1].empty()) {
    std::string keyboard_layout = portions[1];
    if (portions.size() > 2 && !portions[2].empty()) {
      keyboard_layout.append("(");
      keyboard_layout.append(portions[2]);
      keyboard_layout.append(")");
    }
    return keyboard_layout;
  }
  return kDefaultKeyboardLayout;
}

LanguageLibraryImpl::LanguageLibraryImpl()
    : input_method_status_connection_(NULL),
      current_input_method_("", "", ""),
      is_focused_(false) {
  scoped_ptr<InputMethodDescriptors> input_method_descriptors(
      CreateFallbackInputMethodDescriptors());
  current_input_method_ = input_method_descriptors->at(0);
}

LanguageLibraryImpl::~LanguageLibraryImpl() {
  if (input_method_status_connection_) {
    chromeos::DisconnectInputMethodStatus(input_method_status_connection_);
  }
}

LanguageLibraryImpl::Observer::~Observer() {
}

void LanguageLibraryImpl::AddObserver(Observer* observer) {
  observers_.AddObserver(observer);
}

void LanguageLibraryImpl::RemoveObserver(Observer* observer) {
  observers_.RemoveObserver(observer);
}

chromeos::InputMethodDescriptors* LanguageLibraryImpl::GetActiveInputMethods() {
  chromeos::InputMethodDescriptors* result = NULL;
  if (EnsureLoadedAndStarted()) {
    result = chromeos::GetActiveInputMethods(input_method_status_connection_);
  }
  if (!result || result->empty()) {
    result = CreateFallbackInputMethodDescriptors();
  }
  return result;
}

chromeos::InputMethodDescriptors*
LanguageLibraryImpl::GetSupportedInputMethods() {
  chromeos::InputMethodDescriptors* result = NULL;
  if (EnsureLoadedAndStarted()) {
    result = chromeos::GetSupportedInputMethods(
        input_method_status_connection_);
  }
  if (!result || result->empty()) {
    result = CreateFallbackInputMethodDescriptors();
  }
  return result;
}

void LanguageLibraryImpl::ChangeInputMethod(
    const std::string& input_method_id) {
  if (EnsureLoadedAndStarted()) {
    chromeos::ChangeInputMethod(
        input_method_status_connection_, input_method_id.c_str());
  }
}

void LanguageLibraryImpl::SetImePropertyActivated(const std::string& key,
                                                  bool activated) {
  DCHECK(!key.empty());
  if (EnsureLoadedAndStarted()) {
    chromeos::SetImePropertyActivated(
        input_method_status_connection_, key.c_str(), activated);
  }
}

bool LanguageLibraryImpl::InputMethodIsActivated(
    const std::string& input_method_id) {
  scoped_ptr<InputMethodDescriptors> active_input_method_descriptors(
      CrosLibrary::Get()->GetLanguageLibrary()->GetActiveInputMethods());
  for (size_t i = 0; i < active_input_method_descriptors->size(); ++i) {
    if (active_input_method_descriptors->at(i).id == input_method_id) {
      return true;
    }
  }
  return false;
}

bool LanguageLibraryImpl::GetImeConfig(
    const char* section, const char* config_name, ImeConfigValue* out_value) {
  bool success = false;
  if (EnsureLoadedAndStarted()) {
    success = chromeos::GetImeConfig(
        input_method_status_connection_, section, config_name, out_value);
  }
  return success;
}

bool LanguageLibraryImpl::SetImeConfig(
    const char* section, const char* config_name, const ImeConfigValue& value) {
  const ConfigKeyType key = std::make_pair(section, config_name);
  pending_config_requests_.erase(key);
  pending_config_requests_.insert(std::make_pair(key, value));
  FlushImeConfig();
  return pending_config_requests_.empty();
}

void LanguageLibraryImpl::FlushImeConfig() {
  if (EnsureLoadedAndStarted()) {
    LOG(INFO) << "Sending " << pending_config_requests_.size()
              << " set config command(s)";
    InputMethodConfigRequests::iterator iter = pending_config_requests_.begin();
    while (iter != pending_config_requests_.end()) {
      const std::string& section = iter->first.first;
      const std::string& config_name = iter->first.second;
      const ImeConfigValue& value = iter->second;
      if (chromeos::SetImeConfig(input_method_status_connection_,
                                 section.c_str(), config_name.c_str(), value)) {
        // Successfully sent. Remove the command and proceed to the next one.
        pending_config_requests_.erase(iter++);
      } else {
        LOG(ERROR) << "chromeos::SetImeConfig failed. Will retry later: "
                   << section << "/" << config_name;
        ++iter;  // Do not remove the command.
      }
    }
    if (pending_config_requests_.empty()) {
      timer_.Stop();  // no-op if it's not running.
    }
  } else {
    if (!timer_.IsRunning()) {
      static const int64 kTimerIntervalInSec = 1;
      timer_.Start(base::TimeDelta::FromSeconds(kTimerIntervalInSec), this,
                   &LanguageLibraryImpl::FlushImeConfig);
    }
  }
}

// static
void LanguageLibraryImpl::InputMethodChangedHandler(
    void* object, const chromeos::InputMethodDescriptor& current_input_method) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->UpdateCurrentInputMethod(current_input_method);
}

// static
void LanguageLibraryImpl::RegisterPropertiesHandler(
    void* object, const ImePropertyList& prop_list) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->RegisterProperties(prop_list);
}

// static
void LanguageLibraryImpl::UpdatePropertyHandler(
    void* object, const ImePropertyList& prop_list) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->UpdateProperty(prop_list);
}

// static
void LanguageLibraryImpl::FocusChangedHandler(void* object, bool is_focused) {
  LanguageLibraryImpl* language_library =
      static_cast<LanguageLibraryImpl*>(object);
  language_library->FocusChanged(is_focused);
}

bool LanguageLibraryImpl::EnsureStarted() {
  if (input_method_status_connection_) {
    if (chromeos::InputMethodStatusConnectionIsAlive(
            input_method_status_connection_)) {
      return true;
    }
    DLOG(WARNING) << "IBus connection is closed. Trying to reconnect...";
    chromeos::DisconnectInputMethodStatus(input_method_status_connection_);
  }
  input_method_status_connection_ = chromeos::MonitorInputMethodStatus(
      this,
      &InputMethodChangedHandler,
      &RegisterPropertiesHandler,
      &UpdatePropertyHandler,
      &FocusChangedHandler);
  return input_method_status_connection_ != NULL;
}

bool LanguageLibraryImpl::EnsureLoadedAndStarted() {
  return CrosLibrary::Get()->EnsureLoaded() &&
         EnsureStarted();
}

void LanguageLibraryImpl::UpdateCurrentInputMethod(
    const chromeos::InputMethodDescriptor& current_input_method) {
  // Make sure we run on UI thread.
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    DLOG(INFO) << "UpdateCurrentInputMethod (Background thread)";
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        // NewRunnableMethod() copies |current_input_method| by value.
        NewRunnableMethod(
            this, &LanguageLibraryImpl::UpdateCurrentInputMethod,
            current_input_method));
    return;
  }

  DLOG(INFO) << "UpdateCurrentInputMethod (UI thread)";
  if (IsKeyboardLayout(current_input_method.id)) {
    // If the new input method is a keyboard layout, switch the keyboard.
    chromeos::SetCurrentKeyboardLayoutByName(
        GetKeyboardLayoutName(current_input_method.id));
  } else {
    // If the new input method is an IME, change the keyboard back to the
    // default layout (US).  TODO(satorux): What if the user is using a non-US
    // keyboard, such as a Japanese keyboard? We need to rework this.
    chromeos::SetCurrentKeyboardLayoutByName(kDefaultKeyboardLayout);
  }

  current_input_method_ = current_input_method;
  FOR_EACH_OBSERVER(Observer, observers_, InputMethodChanged(this));
}

void LanguageLibraryImpl::RegisterProperties(const ImePropertyList& prop_list) {
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableMethod(
            this, &LanguageLibraryImpl::RegisterProperties, prop_list));
    return;
  }

  // |prop_list| might be empty. This means "clear all properties."
  current_ime_properties_ = prop_list;
  FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
}

void LanguageLibraryImpl::UpdateProperty(const ImePropertyList& prop_list) {
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableMethod(
            this, &LanguageLibraryImpl::UpdateProperty, prop_list));
    return;
  }

  for (size_t i = 0; i < prop_list.size(); ++i) {
    FindAndUpdateProperty(prop_list[i], &current_ime_properties_);
  }
  FOR_EACH_OBSERVER(Observer, observers_, ImePropertiesChanged(this));
}

void LanguageLibraryImpl::FocusChanged(bool is_focused) {
  if (!ChromeThread::CurrentlyOn(ChromeThread::UI)) {
    ChromeThread::PostTask(
        ChromeThread::UI, FROM_HERE,
        NewRunnableMethod(
            this, &LanguageLibraryImpl::FocusChanged, is_focused));
    return;
  }

  is_focused_ = is_focused;
  FOR_EACH_OBSERVER(Observer, observers_, FocusChanged(this));
}

}  // namespace chromeos
<|endoftext|>


<commit_before>// Copyright (c) 2009 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 "base/file_path.h"
#include "base/scoped_temp_dir.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/net/url_request_mock_http_job.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

#if !defined(OS_MACOSX)
// TODO(port): BUG16322
static const FilePath::CharType* kTestDir = FILE_PATH_LITERAL("save_page");

static const char* kAppendedExtension =
#if defined(OS_WIN)
    ".htm";
#else
    ".html";
#endif

#endif  // !defined(OS_MACOSX)

namespace {

class SavePageFinishedObserver : public NotificationObserver {
 public:
  SavePageFinishedObserver() {
    registrar_.Add(this, NotificationType::SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
                   NotificationService::AllSources());
    ui_test_utils::RunMessageLoop();
  }

  GURL page_url() const { return page_url_; }

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    if (type == NotificationType::SAVE_PACKAGE_SUCCESSFULLY_FINISHED) {
      page_url_ = *Details<GURL>(details).ptr();
      MessageLoopForUI::current()->Quit();
    } else {
      NOTREACHED();
    }
  }

 private:
  NotificationRegistrar registrar_;

  GURL page_url_;

  DISALLOW_COPY_AND_ASSIGN(SavePageFinishedObserver);
};

class SavePageBrowserTest : public InProcessBrowserTest {
 protected:
  void SetUp() {
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir_));
    ASSERT_TRUE(save_dir_.CreateUniqueTempDir());
    InProcessBrowserTest::SetUp();
  }

  // Path to directory containing test data.
  FilePath test_dir_;

  // Temporary directory we will save pages to.
  ScopedTempDir save_dir_;
};

#if !defined(OS_MACOSX)
// TODO(port): BUG16322
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveHTMLOnly) {
  FilePath file_name(FILE_PATH_LITERAL("a.htm"));
  GURL url = URLRequestMockHTTPJob::GetMockUrl(
      FilePath(kTestDir).Append(file_name));
  ui_test_utils::NavigateToURL(browser(), url);

  TabContents* current_tab = browser()->GetSelectedTabContents();
  ASSERT_TRUE(current_tab);

  FilePath full_file_name = save_dir_.path().Append(file_name);
  FilePath dir = save_dir_.path().AppendASCII("a_files");
  ASSERT_TRUE(current_tab->SavePage(full_file_name, dir,
                                    SavePackage::SAVE_AS_ONLY_HTML));

  SavePageFinishedObserver observer;

  EXPECT_EQ(url, observer.page_url());
  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
  EXPECT_TRUE(file_util::PathExists(full_file_name));
  EXPECT_FALSE(file_util::PathExists(dir));
  EXPECT_TRUE(file_util::ContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).Append(file_name),
      full_file_name));
}

IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveCompleteHTML) {
  FilePath file_name(FILE_PATH_LITERAL("b.htm"));
  GURL url = URLRequestMockHTTPJob::GetMockUrl(
      FilePath(kTestDir).Append(file_name));
  ui_test_utils::NavigateToURL(browser(), url);

  TabContents* current_tab = browser()->GetSelectedTabContents();
  ASSERT_TRUE(current_tab);

  FilePath full_file_name = save_dir_.path().Append(file_name);
  FilePath dir = save_dir_.path().AppendASCII("b_files");
  ASSERT_TRUE(current_tab->SavePage(full_file_name, dir,
                                    SavePackage::SAVE_AS_COMPLETE_HTML));

  SavePageFinishedObserver observer;

  EXPECT_EQ(url, observer.page_url());
  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
  EXPECT_TRUE(file_util::PathExists(full_file_name));
  EXPECT_TRUE(file_util::PathExists(dir));
  EXPECT_TRUE(file_util::TextContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("b.saved1.htm"),
      full_file_name));
  EXPECT_TRUE(file_util::ContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("1.png"),
      dir.AppendASCII("1.png")));
  EXPECT_TRUE(file_util::ContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("1.css"),
      dir.AppendASCII("1.css")));
}
#endif  // !defined(OS_MACOSX)

IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, NoSave) {
  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kAboutBlankURL));
  ASSERT_TRUE(browser()->command_updater()->SupportsCommand(IDC_SAVE_PAGE));
  EXPECT_FALSE(browser()->command_updater()->IsCommandEnabled(IDC_SAVE_PAGE));
}

#if !defined(OS_MACOSX)
// TODO(port): BUG16322
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, FileNameFromPageTitle) {
  FilePath file_name(FILE_PATH_LITERAL("b.htm"));

  GURL url = URLRequestMockHTTPJob::GetMockUrl(
      FilePath(kTestDir).Append(file_name));
  ui_test_utils::NavigateToURL(browser(), url);

  FilePath full_file_name = save_dir_.path().AppendASCII(
      std::string("Test page for saving page feature") + kAppendedExtension);
  FilePath dir = save_dir_.path().AppendASCII(
      "Test page for saving page feature_files");

  TabContents* current_tab = browser()->GetSelectedTabContents();
  ASSERT_TRUE(current_tab);

  ASSERT_TRUE(current_tab->SavePage(full_file_name, dir,
                                    SavePackage::SAVE_AS_COMPLETE_HTML));
  SavePageFinishedObserver observer;

  EXPECT_EQ(url, observer.page_url());
  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
  EXPECT_TRUE(file_util::PathExists(full_file_name));
  EXPECT_TRUE(file_util::PathExists(dir));
  EXPECT_TRUE(file_util::TextContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("b.saved2.htm"),
      full_file_name));
  EXPECT_TRUE(file_util::ContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("1.png"),
      dir.AppendASCII("1.png")));
  EXPECT_TRUE(file_util::ContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("1.css"),
      dir.AppendASCII("1.css")));
}
#endif  // !defined(OS_MACOSX)

}  // namespace
<commit_msg>Enable browser_tests: SavePageBrowserTest.FileNameFromPageTitle & SavePageBrowserTest.SaveHTMLOnly on the Mac.<commit_after>// Copyright (c) 2009 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 "base/file_path.h"
#include "base/scoped_temp_dir.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_window.h"
#include "chrome/browser/net/url_request_mock_http_job.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/notification_service.h"
#include "chrome/common/url_constants.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"

static const FilePath::CharType* kTestDir = FILE_PATH_LITERAL("save_page");

static const char* kAppendedExtension =
#if defined(OS_WIN)
    ".htm";
#else
    ".html";
#endif

namespace {

class SavePageFinishedObserver : public NotificationObserver {
 public:
  SavePageFinishedObserver() {
    registrar_.Add(this, NotificationType::SAVE_PACKAGE_SUCCESSFULLY_FINISHED,
                   NotificationService::AllSources());
    ui_test_utils::RunMessageLoop();
  }

  GURL page_url() const { return page_url_; }

  virtual void Observe(NotificationType type,
                       const NotificationSource& source,
                       const NotificationDetails& details) {
    if (type == NotificationType::SAVE_PACKAGE_SUCCESSFULLY_FINISHED) {
      page_url_ = *Details<GURL>(details).ptr();
      MessageLoopForUI::current()->Quit();
    } else {
      NOTREACHED();
    }
  }

 private:
  NotificationRegistrar registrar_;

  GURL page_url_;

  DISALLOW_COPY_AND_ASSIGN(SavePageFinishedObserver);
};

class SavePageBrowserTest : public InProcessBrowserTest {
 protected:
  void SetUp() {
    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_dir_));
    ASSERT_TRUE(save_dir_.CreateUniqueTempDir());
    InProcessBrowserTest::SetUp();
  }

  // Path to directory containing test data.
  FilePath test_dir_;

  // Temporary directory we will save pages to.
  ScopedTempDir save_dir_;
};

IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveHTMLOnly) {
  FilePath file_name(FILE_PATH_LITERAL("a.htm"));
  GURL url = URLRequestMockHTTPJob::GetMockUrl(
      FilePath(kTestDir).Append(file_name));
  ui_test_utils::NavigateToURL(browser(), url);

  TabContents* current_tab = browser()->GetSelectedTabContents();
  ASSERT_TRUE(current_tab);

  FilePath full_file_name = save_dir_.path().Append(file_name);
  FilePath dir = save_dir_.path().AppendASCII("a_files");
  ASSERT_TRUE(current_tab->SavePage(full_file_name, dir,
                                    SavePackage::SAVE_AS_ONLY_HTML));

  SavePageFinishedObserver observer;

  EXPECT_EQ(url, observer.page_url());
  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
  EXPECT_TRUE(file_util::PathExists(full_file_name));
  EXPECT_FALSE(file_util::PathExists(dir));
  EXPECT_TRUE(file_util::ContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).Append(file_name),
      full_file_name));
}

IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveCompleteHTML) {
  FilePath file_name(FILE_PATH_LITERAL("b.htm"));
  GURL url = URLRequestMockHTTPJob::GetMockUrl(
      FilePath(kTestDir).Append(file_name));
  ui_test_utils::NavigateToURL(browser(), url);

  TabContents* current_tab = browser()->GetSelectedTabContents();
  ASSERT_TRUE(current_tab);

  FilePath full_file_name = save_dir_.path().Append(file_name);
  FilePath dir = save_dir_.path().AppendASCII("b_files");
  ASSERT_TRUE(current_tab->SavePage(full_file_name, dir,
                                    SavePackage::SAVE_AS_COMPLETE_HTML));

  SavePageFinishedObserver observer;

  EXPECT_EQ(url, observer.page_url());
  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
  EXPECT_TRUE(file_util::PathExists(full_file_name));
  EXPECT_TRUE(file_util::PathExists(dir));
  EXPECT_TRUE(file_util::TextContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("b.saved1.htm"),
      full_file_name));
  EXPECT_TRUE(file_util::ContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("1.png"),
      dir.AppendASCII("1.png")));
  EXPECT_TRUE(file_util::ContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("1.css"),
      dir.AppendASCII("1.css")));
}

IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, NoSave) {
  ui_test_utils::NavigateToURL(browser(), GURL(chrome::kAboutBlankURL));
  ASSERT_TRUE(browser()->command_updater()->SupportsCommand(IDC_SAVE_PAGE));
  EXPECT_FALSE(browser()->command_updater()->IsCommandEnabled(IDC_SAVE_PAGE));
}

IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, FileNameFromPageTitle) {
  FilePath file_name(FILE_PATH_LITERAL("b.htm"));

  GURL url = URLRequestMockHTTPJob::GetMockUrl(
      FilePath(kTestDir).Append(file_name));
  ui_test_utils::NavigateToURL(browser(), url);

  FilePath full_file_name = save_dir_.path().AppendASCII(
      std::string("Test page for saving page feature") + kAppendedExtension);
  FilePath dir = save_dir_.path().AppendASCII(
      "Test page for saving page feature_files");

  TabContents* current_tab = browser()->GetSelectedTabContents();
  ASSERT_TRUE(current_tab);

  ASSERT_TRUE(current_tab->SavePage(full_file_name, dir,
                                    SavePackage::SAVE_AS_COMPLETE_HTML));
  SavePageFinishedObserver observer;

  EXPECT_EQ(url, observer.page_url());
  EXPECT_TRUE(browser()->window()->IsDownloadShelfVisible());
  EXPECT_TRUE(file_util::PathExists(full_file_name));
  EXPECT_TRUE(file_util::PathExists(dir));
  EXPECT_TRUE(file_util::TextContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("b.saved2.htm"),
      full_file_name));
  EXPECT_TRUE(file_util::ContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("1.png"),
      dir.AppendASCII("1.png")));
  EXPECT_TRUE(file_util::ContentsEqual(
      test_dir_.Append(FilePath(kTestDir)).AppendASCII("1.css"),
      dir.AppendASCII("1.css")));
}

}  // namespace
<|endoftext|>