<commit_before>// Scintilla source code edit control
/** @file LexLua.cxx
 ** Lexer for Lua language.
 **
 ** Written by Paul Winwood.
 ** Folder by Alexey Yutkin.
 ** Modified by Marcos E. Wurzius & Philippe Lhoste
 **/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
	return ch >= 0x80 ||
	       (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return ch >= 0x80 ||
	       (isalpha(ch) || ch == '_');
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
	        (isdigit(ch) || toupper(ch) == 'E' ||
	        ch == '.' || ch == '-' || ch == '+' ||
	        (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'));
}

static inline bool IsLuaOperator(int ch) {
	if (ch >= 0x80 || isalnum(ch)) {
		return false;
	}
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' ||
		ch == '{' || ch == '}' || ch == '~' ||
		ch == '[' || ch == ']' || ch == ';' ||
		ch == '<' || ch == '>' || ch == ',' ||
		ch == '.' || ch == '^' || ch == '%' || ch == ':' ||
		ch == '#') {
		return true;
	}
	return false;
}

// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ],
// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on.
// The maximum number of '=' characters allowed is 254.
static int LongDelimCheck(StyleContext &sc) {
	int sep = 1;
	while (sc.GetRelative(sep) == '=' && sep < 0xFF)
		sep++;
	if (sc.GetRelative(sep) == sc.ch)
		return sep;
	return 0;
}

static void ColouriseLuaDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];
	WordList &keywords7 = *keywordlists[6];
	WordList &keywords8 = *keywordlists[7];

	int currentLine = styler.GetLine(startPos);
	// Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level,
	// if we are inside such a string. Block comment was introduced in Lua 5.0,
	// blocks with separators [=[ ... ]=] in Lua 5.1.
	int nestLevel = 0;
	int sepCount = 0;
	if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT) {
		int lineState = styler.GetLineState(currentLine - 1);
		nestLevel = lineState >> 8;
		sepCount = lineState & 0xFF;
	}

	// Do not leak onto next line
	if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
		initStyle = SCE_LUA_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);
	if (startPos == 0 && sc.ch == '#') {
		// shbang line: # is a comment only if first char of the script
		sc.SetState(SCE_LUA_COMMENTLINE);
	}
	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			currentLine = styler.GetLine(sc.currentPos);
			switch (sc.state) {
			case SCE_LUA_LITERALSTRING:
			case SCE_LUA_COMMENT:
				// Inside a literal string or block comment, we set the line state
				styler.SetLineState(currentLine, (nestLevel << 8) | sepCount);
				break;
			default:
				// Reset the line state
				styler.SetLineState(currentLine, 0);
				break;
			}
		}
		if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) {
			// Prevent SCE_LUA_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_LUA_STRING);
		}

		// Handle string line continuation
		if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) &&
		        sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_LUA_OPERATOR) {
			sc.SetState(SCE_LUA_DEFAULT);
		} else if (sc.state == SCE_LUA_NUMBER) {
			// We stop the number definition on non-numerical non-dot non-eE non-sign non-hexdigit char
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || sc.Match('.', '.')) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD4);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD5);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords7.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD7);
				} else if (keywords8.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD8);
				}
				sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) {
			if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_CHARACTER) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) {
			if (sc.ch == '[') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // [[-only allowed to nest
					nestLevel++;
					sc.Forward();
				}
			} else if (sc.ch == ']') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // un-nest with ]]-only
					nestLevel--;
					sc.Forward();
					if (nestLevel == 0) {
						sc.ForwardSetState(SCE_LUA_DEFAULT);
					}
				} else if (sep > 1 && sep == sepCount) {   // ]=]-style delim
					sc.Forward(sep);
					sc.ForwardSetState(SCE_LUA_DEFAULT);
				}
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_LUA_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_LUA_NUMBER);
				if (sc.ch == '0' && toupper(sc.chNext) == 'X') {
					sc.Forward(1);
				}
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_LUA_IDENTIFIER);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_LUA_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_LUA_CHARACTER);
			} else if (sc.ch == '[') {
				sepCount = LongDelimCheck(sc);
				if (sepCount == 0) {
					sc.SetState(SCE_LUA_OPERATOR);
				} else {
					nestLevel = 1;
					sc.SetState(SCE_LUA_LITERALSTRING);
					sc.Forward(sepCount);
				}
			} else if (sc.Match('-', '-')) {
				sc.SetState(SCE_LUA_COMMENTLINE);
				if (sc.Match("--[")) {
					sc.Forward(2);
					sepCount = LongDelimCheck(sc);
					if (sepCount > 0) {
						nestLevel = 1;
						sc.ChangeState(SCE_LUA_COMMENT);
						sc.Forward(sepCount);
					}
				} else {
					sc.Forward();
				}
			} else if (sc.atLineStart && sc.Match('$')) {
				sc.SetState(SCE_LUA_PREPROCESSOR);	// Obsolete since Lua 4.0, but still in old code
			} else if (IsLuaOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_LUA_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int styleNext = styler.StyleAt(startPos);
	char s[10];

	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LUA_WORD) {
			if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') {
				for (unsigned int j = 0; j < 8; j++) {
					if (!iswordchar(styler[i + j])) {
						break;
					}
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) {
					levelCurrent++;
				}
				if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) {
					levelCurrent--;
				}
			}
		} else if (style == SCE_LUA_OPERATOR) {
			if (ch == '{' || ch == '(') {
				levelCurrent++;
			} else if (ch == '}' || ch == ')') {
				levelCurrent--;
			}
		} else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) {
			if (ch == '[') {
				levelCurrent++;
			} else if (ch == ']') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact) {
				lev |= SC_FOLDLEVELWHITEFLAG;
			}
			if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch)) {
			visibleChars++;
		}
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const luaWordListDesc[] = {
	"Keywords",
	"Basic functions",
	"String, (table) & math functions",
	"(coroutines), I/O & system facilities",
	"user1",
	"user2",
	"user3",
	"user4",
	0
};

LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc);
<commit_msg>Patch from Kein-Hong Man properly handles + or - as operators in numbers like 1+2.<commit_after>// Scintilla source code edit control
/** @file LexLua.cxx
 ** Lexer for Lua language.
 **
 ** Written by Paul Winwood.
 ** Folder by Alexey Yutkin.
 ** Modified by Marcos E. Wurzius & Philippe Lhoste
 **/

#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include <stdio.h>

#include "Platform.h"

#include "PropSet.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "KeyWords.h"
#include "Scintilla.h"
#include "SciLexer.h"

// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
	return ch >= 0x80 ||
	       (isalnum(ch) || ch == '.' || ch == '_');
}

static inline bool IsAWordStart(int ch) {
	return ch >= 0x80 ||
	       (isalpha(ch) || ch == '_');
}

static inline bool IsANumberChar(int ch) {
	// Not exactly following number definition (several dots are seen as OK, etc.)
	// but probably enough in most cases.
	return (ch < 0x80) &&
	        (isdigit(ch) || toupper(ch) == 'E' ||
	        ch == '.' || ch == '-' || ch == '+' ||
	        (ch >= 'a' && ch <= 'f') || (ch >= 'A' && ch <= 'F'));
}

static inline bool IsLuaOperator(int ch) {
	if (ch >= 0x80 || isalnum(ch)) {
		return false;
	}
	// '.' left out as it is used to make up numbers
	if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
		ch == '(' || ch == ')' || ch == '=' ||
		ch == '{' || ch == '}' || ch == '~' ||
		ch == '[' || ch == ']' || ch == ';' ||
		ch == '<' || ch == '>' || ch == ',' ||
		ch == '.' || ch == '^' || ch == '%' || ch == ':' ||
		ch == '#') {
		return true;
	}
	return false;
}

// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ],
// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on.
// The maximum number of '=' characters allowed is 254.
static int LongDelimCheck(StyleContext &sc) {
	int sep = 1;
	while (sc.GetRelative(sep) == '=' && sep < 0xFF)
		sep++;
	if (sc.GetRelative(sep) == sc.ch)
		return sep;
	return 0;
}

static void ColouriseLuaDoc(
	unsigned int startPos,
	int length,
	int initStyle,
	WordList *keywordlists[],
	Accessor &styler) {

	WordList &keywords = *keywordlists[0];
	WordList &keywords2 = *keywordlists[1];
	WordList &keywords3 = *keywordlists[2];
	WordList &keywords4 = *keywordlists[3];
	WordList &keywords5 = *keywordlists[4];
	WordList &keywords6 = *keywordlists[5];
	WordList &keywords7 = *keywordlists[6];
	WordList &keywords8 = *keywordlists[7];

	int currentLine = styler.GetLine(startPos);
	// Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level,
	// if we are inside such a string. Block comment was introduced in Lua 5.0,
	// blocks with separators [=[ ... ]=] in Lua 5.1.
	int nestLevel = 0;
	int sepCount = 0;
	if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT) {
		int lineState = styler.GetLineState(currentLine - 1);
		nestLevel = lineState >> 8;
		sepCount = lineState & 0xFF;
	}

	// Do not leak onto next line
	if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
		initStyle = SCE_LUA_DEFAULT;
	}

	StyleContext sc(startPos, length, initStyle, styler);
	if (startPos == 0 && sc.ch == '#') {
		// shbang line: # is a comment only if first char of the script
		sc.SetState(SCE_LUA_COMMENTLINE);
	}
	for (; sc.More(); sc.Forward()) {
		if (sc.atLineEnd) {
			// Update the line state, so it can be seen by next line
			currentLine = styler.GetLine(sc.currentPos);
			switch (sc.state) {
			case SCE_LUA_LITERALSTRING:
			case SCE_LUA_COMMENT:
				// Inside a literal string or block comment, we set the line state
				styler.SetLineState(currentLine, (nestLevel << 8) | sepCount);
				break;
			default:
				// Reset the line state
				styler.SetLineState(currentLine, 0);
				break;
			}
		}
		if (sc.atLineStart && (sc.state == SCE_LUA_STRING)) {
			// Prevent SCE_LUA_STRINGEOL from leaking back to previous line
			sc.SetState(SCE_LUA_STRING);
		}

		// Handle string line continuation
		if ((sc.state == SCE_LUA_STRING || sc.state == SCE_LUA_CHARACTER) &&
		        sc.ch == '\\') {
			if (sc.chNext == '\n' || sc.chNext == '\r') {
				sc.Forward();
				if (sc.ch == '\r' && sc.chNext == '\n') {
					sc.Forward();
				}
				continue;
			}
		}

		// Determine if the current state should terminate.
		if (sc.state == SCE_LUA_OPERATOR) {
			sc.SetState(SCE_LUA_DEFAULT);
		} else if (sc.state == SCE_LUA_NUMBER) {
			// We stop the number definition on non-numerical non-dot non-eE non-sign non-hexdigit char
			if (!IsANumberChar(sc.ch)) {
				sc.SetState(SCE_LUA_DEFAULT);
			} else if (sc.ch == '-' || sc.ch == '+') {
                                if (sc.chPrev != 'E' && sc.chPrev != 'e')
                                        sc.SetState(SCE_LUA_DEFAULT);
                        }
		} else if (sc.state == SCE_LUA_IDENTIFIER) {
			if (!IsAWordChar(sc.ch) || sc.Match('.', '.')) {
				char s[100];
				sc.GetCurrent(s, sizeof(s));
				if (keywords.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD);
				} else if (keywords2.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD2);
				} else if (keywords3.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD3);
				} else if (keywords4.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD4);
				} else if (keywords5.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD5);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords6.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD6);
				} else if (keywords7.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD7);
				} else if (keywords8.InList(s)) {
					sc.ChangeState(SCE_LUA_WORD8);
				}
				sc.SetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) {
			if (sc.atLineEnd) {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_STRING) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\"') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_CHARACTER) {
			if (sc.ch == '\\') {
				if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
					sc.Forward();
				}
			} else if (sc.ch == '\'') {
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			} else if (sc.atLineEnd) {
				sc.ChangeState(SCE_LUA_STRINGEOL);
				sc.ForwardSetState(SCE_LUA_DEFAULT);
			}
		} else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) {
			if (sc.ch == '[') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // [[-only allowed to nest
					nestLevel++;
					sc.Forward();
				}
			} else if (sc.ch == ']') {
				int sep = LongDelimCheck(sc);
				if (sep == 1 && sepCount == 1) {    // un-nest with ]]-only
					nestLevel--;
					sc.Forward();
					if (nestLevel == 0) {
						sc.ForwardSetState(SCE_LUA_DEFAULT);
					}
				} else if (sep > 1 && sep == sepCount) {   // ]=]-style delim
					sc.Forward(sep);
					sc.ForwardSetState(SCE_LUA_DEFAULT);
				}
			}
		}

		// Determine if a new state should be entered.
		if (sc.state == SCE_LUA_DEFAULT) {
			if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
				sc.SetState(SCE_LUA_NUMBER);
				if (sc.ch == '0' && toupper(sc.chNext) == 'X') {
					sc.Forward(1);
				}
			} else if (IsAWordStart(sc.ch)) {
				sc.SetState(SCE_LUA_IDENTIFIER);
			} else if (sc.ch == '\"') {
				sc.SetState(SCE_LUA_STRING);
			} else if (sc.ch == '\'') {
				sc.SetState(SCE_LUA_CHARACTER);
			} else if (sc.ch == '[') {
				sepCount = LongDelimCheck(sc);
				if (sepCount == 0) {
					sc.SetState(SCE_LUA_OPERATOR);
				} else {
					nestLevel = 1;
					sc.SetState(SCE_LUA_LITERALSTRING);
					sc.Forward(sepCount);
				}
			} else if (sc.Match('-', '-')) {
				sc.SetState(SCE_LUA_COMMENTLINE);
				if (sc.Match("--[")) {
					sc.Forward(2);
					sepCount = LongDelimCheck(sc);
					if (sepCount > 0) {
						nestLevel = 1;
						sc.ChangeState(SCE_LUA_COMMENT);
						sc.Forward(sepCount);
					}
				} else {
					sc.Forward();
				}
			} else if (sc.atLineStart && sc.Match('$')) {
				sc.SetState(SCE_LUA_PREPROCESSOR);	// Obsolete since Lua 4.0, but still in old code
			} else if (IsLuaOperator(static_cast<char>(sc.ch))) {
				sc.SetState(SCE_LUA_OPERATOR);
			}
		}
	}
	sc.Complete();
}

static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
                       Accessor &styler) {
	unsigned int lengthDoc = startPos + length;
	int visibleChars = 0;
	int lineCurrent = styler.GetLine(startPos);
	int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
	int levelCurrent = levelPrev;
	char chNext = styler[startPos];
	bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
	int styleNext = styler.StyleAt(startPos);
	char s[10];

	for (unsigned int i = startPos; i < lengthDoc; i++) {
		char ch = chNext;
		chNext = styler.SafeGetCharAt(i + 1);
		int style = styleNext;
		styleNext = styler.StyleAt(i + 1);
		bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
		if (style == SCE_LUA_WORD) {
			if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') {
				for (unsigned int j = 0; j < 8; j++) {
					if (!iswordchar(styler[i + j])) {
						break;
					}
					s[j] = styler[i + j];
					s[j + 1] = '\0';
				}

				if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) {
					levelCurrent++;
				}
				if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) {
					levelCurrent--;
				}
			}
		} else if (style == SCE_LUA_OPERATOR) {
			if (ch == '{' || ch == '(') {
				levelCurrent++;
			} else if (ch == '}' || ch == ')') {
				levelCurrent--;
			}
		} else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) {
			if (ch == '[') {
				levelCurrent++;
			} else if (ch == ']') {
				levelCurrent--;
			}
		}

		if (atEOL) {
			int lev = levelPrev;
			if (visibleChars == 0 && foldCompact) {
				lev |= SC_FOLDLEVELWHITEFLAG;
			}
			if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
				lev |= SC_FOLDLEVELHEADERFLAG;
			}
			if (lev != styler.LevelAt(lineCurrent)) {
				styler.SetLevel(lineCurrent, lev);
			}
			lineCurrent++;
			levelPrev = levelCurrent;
			visibleChars = 0;
		}
		if (!isspacechar(ch)) {
			visibleChars++;
		}
	}
	// Fill in the real level of the next line, keeping the current flags as they will be filled in later

	int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
	styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

static const char * const luaWordListDesc[] = {
	"Keywords",
	"Basic functions",
	"String, (table) & math functions",
	"(coroutines), I/O & system facilities",
	"user1",
	"user2",
	"user3",
	"user4",
	0
};

LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc);
<|endoftext|>


<commit_before>#include "Logger.h"

#include <QtGlobal>
#include <QCoreApplication>
#include <QDesktopServices>
#include <QDir>
#include <QTime>

#include <fstream>
#include <iostream>

using namespace std;
ofstream logfile;

namespace Logging {

void logHandler(QtMsgType type, const char *msg) {

    logfile << QTime::currentTime().toString().toUtf8().data();
    switch (type) {
        case QtDebugMsg:
            logfile << " Debug: " << msg << endl;
            break;
        case QtCriticalMsg:
            logfile << " Critical: " << msg << endl;
            break;
        case QtWarningMsg:
            logfile << " Warning: " << msg << endl;
            break;
        case QtFatalMsg:
            logfile << " Fatal: " << msg << endl;
            abort();
    }
    logfile.flush();

    cout << QTime::currentTime().toString().toUtf8().data() << "\t" << msg << endl << flush;
}

QDir
loggingDirectory()
{
#ifdef Q_OS_LINUX
    return QDir::home().filePath( ".local/share/Zulip" );
#elif defined(Q_OS_WIN)
    return QDir(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
#elif defined(Q_OS_MAC)
    return QDir( QDir::homePath() + "/Library/Logs" );
#endif
}

void setupLogging() {
    QDir logFileDir = loggingDirectory();
    logFileDir.mkpath(logFileDir.absolutePath());

    const QString filePath = logFileDir.absoluteFilePath("Zulip.log");
    logfile.open( filePath.toLocal8Bit(), ios::app );

    cout.flush();
    qInstallMsgHandler( logHandler );
}

}
<commit_msg>Hide Warning and Debug messages from console<commit_after>#include "Logger.h"

#include <QtGlobal>
#include <QCoreApplication>
#include <QDesktopServices>
#include <QDir>
#include <QTime>

#include <fstream>
#include <iostream>

using namespace std;
ofstream logfile;

namespace Logging {

void logHandler(QtMsgType type, const char *msg) {

    logfile << QTime::currentTime().toString().toUtf8().data();
    switch (type) {
        case QtDebugMsg:
            logfile << " Debug: " << msg << endl;
            break;
        case QtCriticalMsg:
            logfile << " Critical: " << msg << endl;
            break;
        case QtWarningMsg:
            logfile << " Warning: " << msg << endl;
            break;
        case QtFatalMsg:
            logfile << " Fatal: " << msg << endl;
            abort();
    }
    logfile.flush();

    // Only show Critical and Fatal debug messages on the console
    if ((type == QtDebugMsg || type == QtWarningMsg)) {
        return;
    }

    cout << QTime::currentTime().toString().toUtf8().data() << "\t" << msg << endl << flush;
}

QDir
loggingDirectory()
{
#ifdef Q_OS_LINUX
    return QDir::home().filePath( ".local/share/Zulip" );
#elif defined(Q_OS_WIN)
    return QDir(QDesktopServices::storageLocation(QDesktopServices::DataLocation));
#elif defined(Q_OS_MAC)
    return QDir( QDir::homePath() + "/Library/Logs" );
#endif
}

void setupLogging() {
    QDir logFileDir = loggingDirectory();
    logFileDir.mkpath(logFileDir.absolutePath());

    const QString filePath = logFileDir.absoluteFilePath("Zulip.log");
    logfile.open( filePath.toLocal8Bit(), ios::app );

    cout.flush();
    qInstallMsgHandler( logHandler );
}

}
<|endoftext|>


<commit_before>#include "Logger.hpp"
#include "CAmxDebugManager.hpp"
#include "LogManager.hpp"
#include "amx/amx2.h"

#include <fmt/format.h>

Logger::Logger(std::string modulename) :
	_module_name(std::move(modulename))
{
	LogConfigReader::Get()->GetLoggerConfig(_module_name, _config);
	LogManager::Get()->RegisterLogger(this);
}

Logger::~Logger()
{
	LogManager::Get()->UnregisterLogger(this);
}

bool Logger::Log(LogLevel level, const char *msg,
	std::vector<samplog::AmxFuncCallInfo> const &call_info)
{
	if (!IsLogLevel(level))
		return false;

	LogManager::Get()->QueueLogMessage(std::unique_ptr<CMessage>(new CMessage(
		_module_name, level, msg ? msg : "", std::vector<samplog::AmxFuncCallInfo>(call_info))));
	return true;
}

bool Logger::Log(LogLevel level, const char *msg)
{
	if (!IsLogLevel(level))
		return false;

	LogManager::Get()->QueueLogMessage(std::unique_ptr<CMessage>(new CMessage(
		_module_name, level, msg ? msg : "", { })));
	return true;
}

bool Logger::LogNativeCall(AMX * const amx, cell * const params,
	const char *name, const char *params_format)
{
	if (amx == nullptr)
		return false;

	if (params == nullptr)
		return false;

	if (name == nullptr || strlen(name) == 0)
		return false;

	if (params_format == nullptr) // params_format == "" is valid (no parameters)
		return false;

	if (!IsLogLevel(LogLevel::DEBUG))
		return false;

	size_t format_len = strlen(params_format);

	fmt::MemoryWriter fmt_msg;
	fmt_msg << name << '(';

	for (int i = 0; i != format_len; ++i)
	{
		if (i != 0)
			fmt_msg << ", ";

		cell current_param = params[i + 1];
		switch (params_format[i])
		{
			case 'd': //decimal
			case 'i': //integer
				fmt_msg << static_cast<int>(current_param);
				break;
			case 'f': //float
				fmt_msg << amx_ctof(current_param);
				break;
			case 'h': //hexadecimal
			case 'x': //
				fmt_msg << fmt::hex(current_param);
				break;
			case 'b': //binary
				fmt_msg << fmt::bin(current_param);
				break;
			case 's': //string
				fmt_msg << '"' << amx_GetCppString(amx, current_param) << '"';
				break;
			case '*': //censored output
				fmt_msg << "\"*****\"";
				break;
			case 'r': //reference
			{
				cell *addr_dest = nullptr;
				amx_GetAddr(amx, current_param, &addr_dest);
				fmt_msg << "0x" << fmt::pad(fmt::hexu(reinterpret_cast<unsigned int>(addr_dest)), 8, '0');
			}	break;
			case 'p': //pointer-value
				fmt_msg << "0x" << fmt::pad(fmt::hexu(current_param), 8, '0');
				break;
			default:
				return false; //unrecognized format specifier
		}
	}
	fmt_msg << ')';

	std::vector<samplog::AmxFuncCallInfo> call_info;
	CAmxDebugManager::Get()->GetFunctionCallTrace(amx, call_info);

	LogManager::Get()->QueueLogMessage(std::unique_ptr<CMessage>(new CMessage(
		_module_name, LogLevel::DEBUG, fmt_msg.str(), std::move(call_info))));
	return true;
}

samplog::ILogger *samplog_CreateLogger(const char *module)
{
	return new Logger(module);
}
<commit_msg>prohibit use of internal log-core logger name<commit_after>#include "Logger.hpp"
#include "CAmxDebugManager.hpp"
#include "LogManager.hpp"
#include "amx/amx2.h"

#include <fmt/format.h>
#include <cstring>

Logger::Logger(std::string modulename) :
	_module_name(std::move(modulename))
{
	LogConfigReader::Get()->GetLoggerConfig(_module_name, _config);
	LogManager::Get()->RegisterLogger(this);
}

Logger::~Logger()
{
	LogManager::Get()->UnregisterLogger(this);
}

bool Logger::Log(LogLevel level, const char *msg,
	std::vector<samplog::AmxFuncCallInfo> const &call_info)
{
	if (!IsLogLevel(level))
		return false;

	LogManager::Get()->QueueLogMessage(std::unique_ptr<CMessage>(new CMessage(
		_module_name, level, msg ? msg : "", std::vector<samplog::AmxFuncCallInfo>(call_info))));
	return true;
}

bool Logger::Log(LogLevel level, const char *msg)
{
	if (!IsLogLevel(level))
		return false;

	LogManager::Get()->QueueLogMessage(std::unique_ptr<CMessage>(new CMessage(
		_module_name, level, msg ? msg : "", { })));
	return true;
}

bool Logger::LogNativeCall(AMX * const amx, cell * const params,
	const char *name, const char *params_format)
{
	if (amx == nullptr)
		return false;

	if (params == nullptr)
		return false;

	if (name == nullptr || strlen(name) == 0)
		return false;

	if (params_format == nullptr) // params_format == "" is valid (no parameters)
		return false;

	if (!IsLogLevel(LogLevel::DEBUG))
		return false;

	size_t format_len = strlen(params_format);

	fmt::MemoryWriter fmt_msg;
	fmt_msg << name << '(';

	for (int i = 0; i != format_len; ++i)
	{
		if (i != 0)
			fmt_msg << ", ";

		cell current_param = params[i + 1];
		switch (params_format[i])
		{
			case 'd': //decimal
			case 'i': //integer
				fmt_msg << static_cast<int>(current_param);
				break;
			case 'f': //float
				fmt_msg << amx_ctof(current_param);
				break;
			case 'h': //hexadecimal
			case 'x': //
				fmt_msg << fmt::hex(current_param);
				break;
			case 'b': //binary
				fmt_msg << fmt::bin(current_param);
				break;
			case 's': //string
				fmt_msg << '"' << amx_GetCppString(amx, current_param) << '"';
				break;
			case '*': //censored output
				fmt_msg << "\"*****\"";
				break;
			case 'r': //reference
			{
				cell *addr_dest = nullptr;
				amx_GetAddr(amx, current_param, &addr_dest);
				fmt_msg << "0x" << fmt::pad(fmt::hexu(reinterpret_cast<unsigned int>(addr_dest)), 8, '0');
			}	break;
			case 'p': //pointer-value
				fmt_msg << "0x" << fmt::pad(fmt::hexu(current_param), 8, '0');
				break;
			default:
				return false; //unrecognized format specifier
		}
	}
	fmt_msg << ')';

	std::vector<samplog::AmxFuncCallInfo> call_info;
	CAmxDebugManager::Get()->GetFunctionCallTrace(amx, call_info);

	LogManager::Get()->QueueLogMessage(std::unique_ptr<CMessage>(new CMessage(
		_module_name, LogLevel::DEBUG, fmt_msg.str(), std::move(call_info))));
	return true;
}

samplog::ILogger *samplog_CreateLogger(const char *module)
{
	if (strstr(module, "log-core") != nullptr)
		return nullptr;

	return new Logger(module);
}
<|endoftext|>


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

    This file is part of Magnum.

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

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include "Object.h"
#include "Scene.h"

using namespace std;

namespace Magnum {

void Object::setParent(Object* parent) {
    if(_parent == parent) return;

    /* Set new parent and add the object to new parent children list */
    if(parent != nullptr) {

        /* Only Fry can be his own grandfather */
        Object* p = parent;
        while(p != nullptr && p->parent() != p) {
            if(p == this) return;
            p = p->parent();
        }

        parent->_children.insert(this);
    }

    /* Remove the object from old parent children list */
    if(_parent != nullptr)
        _parent->_children.erase(this);

    _parent = parent;

    setDirty();
}

Matrix4 Object::absoluteTransformation(Camera* camera) {
    Matrix4 t = _transformation;

    /* Shortcut for absolute transformation of camera relative to itself */
    if(camera == this) return Matrix4();

    Object* p = parent();
    while(p != nullptr) {
        t = p->transformation()*t;

        /* We got to the scene, multiply with camera matrix */
        if(p->parent() == p) {
            if(camera && camera->scene() == scene())
                t = camera->cameraMatrix()*t;

            break;
        }

        p = p->parent();
    }

    return t;
}

Object::~Object() {
    /* Remove the object from parent's children */
    setParent(nullptr);

    /* Delete all children */
    for(set<Object*>::const_iterator it = _children.begin(); it != _children.end(); ++it)
        delete *it;
}

Scene* Object::scene() const {
    /* Goes up the family tree until it finds object which is parent of itself
       (that's the scene) */
    Object* p = parent();
    while(p != nullptr) {
        if(p->parent() == p) return static_cast<Scene*>(p);
        p = p->parent();
    }

    return nullptr;
}

void Object::setDirty() {
    /* The object (and all its children) are already dirty, nothing to do */
    if(dirty) return;

    dirty = true;

    /* Make all children dirty */
    for(set<Object*>::iterator it = _children.begin(); it != _children.end(); ++it)
        (*it)->setDirty();
}

void Object::setClean() {
    /* The object (and all its parents) is already clean, nothing to do */
    if(!dirty) return;

    dirty = false;

    /* Make all parents clean */
    if(_parent != nullptr && _parent != this) _parent->setClean();
}

}
<commit_msg>Fixed crash on deletion of Object children.<commit_after>/*
    Copyright © 2010, 2011, 2012 Vladimír Vondruš <mosra@centrum.cz>

    This file is part of Magnum.

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

    Magnum is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU Lesser General Public License version 3 for more details.
*/

#include "Object.h"
#include "Scene.h"

using namespace std;

namespace Magnum {

void Object::setParent(Object* parent) {
    if(_parent == parent) return;

    /* Set new parent and add the object to new parent children list */
    if(parent != nullptr) {

        /* Only Fry can be his own grandfather */
        Object* p = parent;
        while(p != nullptr && p->parent() != p) {
            if(p == this) return;
            p = p->parent();
        }

        parent->_children.insert(this);
    }

    /* Remove the object from old parent children list */
    if(_parent != nullptr)
        _parent->_children.erase(this);

    _parent = parent;

    setDirty();
}

Matrix4 Object::absoluteTransformation(Camera* camera) {
    Matrix4 t = _transformation;

    /* Shortcut for absolute transformation of camera relative to itself */
    if(camera == this) return Matrix4();

    Object* p = parent();
    while(p != nullptr) {
        t = p->transformation()*t;

        /* We got to the scene, multiply with camera matrix */
        if(p->parent() == p) {
            if(camera && camera->scene() == scene())
                t = camera->cameraMatrix()*t;

            break;
        }

        p = p->parent();
    }

    return t;
}

Object::~Object() {
    /* Remove the object from parent's children */
    setParent(nullptr);

    /* Delete all children */
    while(!_children.empty())
        delete *_children.begin();
}

Scene* Object::scene() const {
    /* Goes up the family tree until it finds object which is parent of itself
       (that's the scene) */
    Object* p = parent();
    while(p != nullptr) {
        if(p->parent() == p) return static_cast<Scene*>(p);
        p = p->parent();
    }

    return nullptr;
}

void Object::setDirty() {
    /* The object (and all its children) are already dirty, nothing to do */
    if(dirty) return;

    dirty = true;

    /* Make all children dirty */
    for(set<Object*>::iterator it = _children.begin(); it != _children.end(); ++it)
        (*it)->setDirty();
}

void Object::setClean() {
    /* The object (and all its parents) is already clean, nothing to do */
    if(!dirty) return;

    dirty = false;

    /* Make all parents clean */
    if(_parent != nullptr && _parent != this) _parent->setClean();
}

}
<|endoftext|>


<commit_before>// -*- mode: c++, coding: utf-8 -*-
/**
 * tbrpg – Text based roll playing game
 *
 * Copyright © 2012  Mattias Andrée (maandree@kth.se)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef __GUARD_OBJECT_HPP__
#define __GUARD_OBJECT_HPP__

#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <unordered_map>

/**
 * Text based roll playing game
 *
 * DD2387 Program construction with C++
 * Laboration 3
 *
 * @author  Mattias Andrée <maandree@kth.se>
 */
namespace tbrpg
{
  /**
   * Master super class
   */
  class Object
  {
  public:
    /**
     * Class inheritance vector
     */
    std::vector<short> class_inheritance;

    /**
     * Construction
     */
    Object();

    /**
     * Copy constructor
     *
     * @param  original  The object to clone
     */
    Object(const Object& original);

    /**
     * Copy constructor
     *
     * @param  original  The object to clone
     */
    Object(Object& original);

    /**
     * Move constructor
     *
     * @param  original  The object to clone
     */
    Object(Object&& original);

    /**
     * Destructor
     */
    virtual ~Object();

    /**
     * Assignment operator
     *
     * @param   original  The reference object
     * @return            The invoked object
     */
    virtual Object& operator =(const Object& original);

    /**
     * Assignment operator
     *
     * @param   original  The reference object
     * @return            The invoked object
     */
    virtual Object& operator =(Object& original);

    /**
     * Move operator
     *
     * @param   original  The moved object, its resourced will be moved
     * @return            The invoked object
     */
    virtual Object& operator =(Object&& original);

    /**
     * Equality evaluator
     *
     * @param   other  The other comparand
     * @return         Whether the instances are equal
     */
    virtual bool operator ==(const Object& other) const;

    /**
     * 'Instance of' evaluator
     *
     * @param   other  The other comparand
     * @return         Whether the left comparand is an instance of the right comparand's class
     */
    virtual bool operator >=(const Object& other) const;

    /**
     * Reversed 'instance of' evaluator
     *
     * @param   other  The other comparand
     * @return         Whether the right comparand is an instance of the left comparand's class
     */
    virtual bool operator <=(const Object& other) const;

  protected:
    /**
     * Copy method
     *
     * @param  self      The object to modify
     * @param  original  The reference object
     */
    static void __copy__(Object& self, const Object& original);

  public:
    /**
     * Hash method
     *
     * @return  The object's hash code
     */
    size_t hash() const;

  };
}

namespace std
{
  template<>
  class hash<tbrpg::Object>
  {
  public:
    size_t operator()(const tbrpg::Object& elem) const
    {
       return elem.hash();
    }
  };
}

#endif//__GUARD_OBJECT_HPP__

<commit_msg>m<commit_after>// -*- mode: c++, coding: utf-8 -*-
/**
 * tbrpg – Text based roll playing game
 *
 * Copyright © 2012  Mattias Andrée (maandree@kth.se)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
#ifndef __GUARD_OBJECT_HPP__
#define __GUARD_OBJECT_HPP__

#include <stdlib.h>
#include <algorithm>
#include <vector>
#include <unordered_map>

/**
 * Text based roll playing game
 *
 * DD2387 Program construction with C++
 * Laboration 3
 *
 * @author  Mattias Andrée <maandree@kth.se>
 */
namespace tbrpg
{
  /**
   * Master super class
   */
  class Object
  {
  public:
    /**
     * Class inheritance vector
     */
    std::vector<short> class_inheritance;

    /**
     * Construction
     */
    Object();

    /**
     * Copy constructor
     *
     * @param  original  The object to clone
     */
    Object(const Object& original);

    /**
     * Copy constructor
     *
     * @param  original  The object to clone
     */
    Object(Object& original);

    /**
     * Move constructor
     *
     * @param  original  The object to clone
     */
    Object(Object&& original);

    /**
     * Destructor
     */
    virtual ~Object();

    /**
     * Assignment operator
     *
     * @param   original  The reference object
     * @return            The invoked object
     */
    virtual Object& operator =(const Object& original);

    /**
     * Assignment operator
     *
     * @param   original  The reference object
     * @return            The invoked object
     */
    virtual Object& operator =(Object& original);

    /**
     * Move operator
     *
     * @param   original  The moved object, its resourced will be moved
     * @return            The invoked object
     */
    virtual Object& operator =(Object&& original);

    /**
     * Equality evaluator
     *
     * @param   other  The other comparand
     * @return         Whether the instances are equal
     */
    virtual bool operator ==(const Object& other) const;

    /**
     * 'Instance of' evaluator
     *
     * @param   other  The other comparand
     * @return         Whether the left comparand is an instance of the right comparand's class
     */
    bool operator >=(const Object& other) const;

    /**
     * Reversed 'instance of' evaluator
     *
     * @param   other  The other comparand
     * @return         Whether the right comparand is an instance of the left comparand's class
     */
    bool operator <=(const Object& other) const;

  protected:
    /**
     * Copy method
     *
     * @param  self      The object to modify
     * @param  original  The reference object
     */
    static void __copy__(Object& self, const Object& original);

  public:
    /**
     * Hash method
     *
     * @return  The object's hash code
     */
    size_t hash() const;

  };
}

namespace std
{
  template<>
  class hash<tbrpg::Object>
  {
  public:
    size_t operator()(const tbrpg::Object& elem) const
    {
       return elem.hash();
    }
  };
}

#endif//__GUARD_OBJECT_HPP__

<|endoftext|>


<commit_before>//---------------------------------------------------------------------------//
//!
//! \file   Utility_TetrahedronHelpers.cpp
//! \author Alex Robinson, Eli Moll
//! \brief  Tetrahedron helper functions
//!
//---------------------------------------------------------------------------//

// Std Lib Includes
#include <math.h>

// Trilinos Includes
#include <Teuchos_ScalarTraits.hpp>

// FRENSIE Includes
#include "Utility_TetrahedronHelpers.hpp"
#include "Utility_ContractException.hpp"
#include <moab/Matrix3.hpp>

namespace Utility{

// Calculate the volume of a tetrahedron
double calculateTetrahedronVolume( const double vertex_a[3],
				   const double vertex_b[3],
				   const double vertex_c[3],
				   const double vertex_d[3] )
{
  double a1 = vertex_a[0] - vertex_d[0];
  double a2 = vertex_a[1] - vertex_d[1];
  double a3 = vertex_a[2] - vertex_d[2];
  double b1 = vertex_b[0] - vertex_d[0];
  double b2 = vertex_b[1] - vertex_d[1];
  double b3 = vertex_b[2] - vertex_d[2];
  double c1 = vertex_c[0] - vertex_d[0];
  double c2 = vertex_c[1] - vertex_d[1];
  double c3 = vertex_c[2] - vertex_d[2];

  double volume =
    fabs( a1*(b2*c3-b3*c2) + a2*(b3*c1-b1*c3) + a3*(b1*c2-b2*c1) )/6.0;

  testPostcondition( !Teuchos::ScalarTraits<double>::isnaninf( volume ) );
  testPostcondition( volume > 0.0 );

  return volume;
}

// Calculate the Barycentric Transform Matrix
double* calculateBarycentricTransformMatrix(  const double vertex_a[3],
				             const double vertex_b[3],
				             const double vertex_c[3],
				             const double vertex_d[3] )
{
  double t1 = 1.0;//vertex_a[0] - vertex_d[0];
  double t2 = 5.0;//vertex_b[0] - vertex_d[0];
  double t3 = 1.0;//vertex_c[0] - vertex_d[0];
  double t4 = 1.0;//vertex_a[1] - vertex_d[1];
  double t5 = 1.0;//vertex_b[1] - vertex_d[1];
  double t6 = 1.0;//vertex_c[1] - vertex_d[1];
  double t7 = 1.0;//vertex_a[2] - vertex_d[2];
  double t8 = 1.0;//vertex_b[2] - vertex_d[2];
  double t9 = 0.0;//vertex_c[2] - vertex_d[2];

  double* t[9] = { t1, t2, t3, t4, t5, t6, t7, t8, t9 };

  moab::Matrix3 T( t );

  return T.array();
}

} // end Utility namespace

//---------------------------------------------------------------------------//
// end Utility_TetrahedronHelpers.cpp
//---------------------------------------------------------------------------//
<commit_msg>Arraytrans<commit_after>//---------------------------------------------------------------------------//
//!
//! \file   Utility_TetrahedronHelpers.cpp
//! \author Alex Robinson, Eli Moll
//! \brief  Tetrahedron helper functions
//!
//---------------------------------------------------------------------------//

// Std Lib Includes
#include <math.h>

// Trilinos Includes
#include <Teuchos_ScalarTraits.hpp>

// FRENSIE Includes
#include "Utility_TetrahedronHelpers.hpp"
#include "Utility_ContractException.hpp"
#include <moab/Matrix3.hpp>

namespace Utility{

// Calculate the volume of a tetrahedron
double calculateTetrahedronVolume( const double vertex_a[3],
				   const double vertex_b[3],
				   const double vertex_c[3],
				   const double vertex_d[3] )
{
  double a1 = vertex_a[0] - vertex_d[0];
  double a2 = vertex_a[1] - vertex_d[1];
  double a3 = vertex_a[2] - vertex_d[2];
  double b1 = vertex_b[0] - vertex_d[0];
  double b2 = vertex_b[1] - vertex_d[1];
  double b3 = vertex_b[2] - vertex_d[2];
  double c1 = vertex_c[0] - vertex_d[0];
  double c2 = vertex_c[1] - vertex_d[1];
  double c3 = vertex_c[2] - vertex_d[2];

  double volume =
    fabs( a1*(b2*c3-b3*c2) + a2*(b3*c1-b1*c3) + a3*(b1*c2-b2*c1) )/6.0;

  testPostcondition( !Teuchos::ScalarTraits<double>::isnaninf( volume ) );
  testPostcondition( volume > 0.0 );

  return volume;
}

// Calculate the Barycentric Transform Matrix
double* calculateBarycentricTransformMatrix(  const double vertex_a[3],
				              const double vertex_b[3],
				              const double vertex_c[3],
				              const double vertex_d[3] )
{
  double t1 = 1.0;//vertex_a[0] - vertex_d[0];
  double t2 = 5.0;//vertex_b[0] - vertex_d[0];
  double t3 = 1.0;//vertex_c[0] - vertex_d[0];
  double t4 = 1.0;//vertex_a[1] - vertex_d[1];
  double t5 = 1.0;//vertex_b[1] - vertex_d[1];
  double t6 = 1.0;//vertex_c[1] - vertex_d[1];
  double t7 = 1.0;//vertex_a[2] - vertex_d[2];
  double t8 = 1.0;//vertex_b[2] - vertex_d[2];
  double t9 = 1.0;//vertex_c[2] - vertex_d[2];

  moab::Matrix3 T( t1, t2, t3, t4, t5, t6, t7, t8, t9 );

  return T.array();
}

} // end Utility namespace

//---------------------------------------------------------------------------//
// end Utility_TetrahedronHelpers.cpp
//---------------------------------------------------------------------------//
<|endoftext|>


<commit_before>/*********************************************************************************
* Copyright (c) 2013 David D. Marshall <ddmarsha@calpoly.edu>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    David D. Marshall - initial code and implementation
********************************************************************************/

#ifndef eli_geom_surface_piecewise_body_of_revolution_creator_hpp
#define eli_geom_surface_piecewise_body_of_revolution_creator_hpp

#include <list>
#include <iterator>

#include "eli/code_eli.hpp"

#include "eli/util/tolerance.hpp"

#include "eli/geom/curve/piecewise.hpp"
#include "eli/geom/curve/piecewise_creator.hpp"

#include "eli/geom/surface/piecewise.hpp"
#include "eli/geom/surface/bezier.hpp"

namespace eli
{
  namespace geom
  {
    namespace surface
    {
      template<typename data__, unsigned short dim__, typename tol__>
      bool create_body_of_revolution(piecewise<bezier, data__, dim__, tol__> &ps,
                                     const eli::geom::curve::piecewise<eli::geom::curve::bezier, data__, dim__, tol__> &pc,
                                     int axis, bool outward_normal)
      {
        typedef piecewise<bezier, data__, dim__, tol__> piecewise_surface_type;
        typedef eli::geom::curve::piecewise<eli::geom::curve::bezier, data__, dim__, tol__> piecewise_curve_type;
        typedef eli::geom::curve::piecewise_circle_creator<data__, dim__, tol__> circle_creator_type;
        typedef typename piecewise_curve_type::curve_type curve_type;
        typedef typename piecewise_surface_type::surface_type surface_type;
        typedef typename curve_type::point_type point_type;
        typedef typename curve_type::data_type data_type;
        typedef typename curve_type::index_type index_type;

        curve_type c, arc;
        surface_type s[4];
        piecewise_curve_type pc_circle;
        point_type origin, normal, start;
        data_type du, dv;
        index_type i, j, pp, qq, nu=pc.number_segments(), nv=4, udim, vdim;

        // resize the surface
        ps.init_uv(nu, nv);

        // set the axis of rotation
        switch(axis)
        {
          case(0):
          {
            normal << 1, 0, 0;
            break;
          }
          case(1):
          {
            normal << 0, 1, 0;
            break;
          }
          case(2):
          {
            normal << 0, 0, 1;
            break;
          }
          default:
          {
            assert(false);
            return false;
          }
        }
        if (outward_normal)
        {
          normal*=-1;
        }

        // cycle through each curve segment
        circle_creator_type circle_creator;
        for (pp=0; pp<nu; ++pp)
        {
          // resize the surface patch
          udim=c.dimension();
          vdim=3;
          pc.get(c, du, pp);
          s[0].resize(udim, vdim);
          s[1].resize(udim, vdim);
          s[2].resize(udim, vdim);
          s[3].resize(udim, vdim);

          // cycle through each control point in current curve and create patch control points
          for (i=0; i<=udim; ++i)
          {
            // set up the vectors for this circle
            start=c.get_control_point(i);
            origin=normal.dot(start)*normal;

            // get the circle
            circle_creator.set(start, origin, normal);
            if (!circle_creator.create(pc_circle))
            {
              assert(false);
              return false;
            }

            // for each segment of circle set the control points
            for (qq=0; qq<4; ++qq)
            {
              pc_circle.get(arc, dv, qq);
              for (j=0; j<4; ++j)
              {
                s[qq].set_control_point(arc.get_control_point(j), i, j);
              }
            }
          }

          // set the surface patches
          for (qq=0; qq<4; ++qq)
          {
            ps.set(s[qq], pp, qq);
          }
        }

        return true;
      }
    }
  }
}
#endif
<commit_msg>Pass option to match curve u-parameterization when revolving.<commit_after>/*********************************************************************************
* Copyright (c) 2013 David D. Marshall <ddmarsha@calpoly.edu>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    David D. Marshall - initial code and implementation
********************************************************************************/

#ifndef eli_geom_surface_piecewise_body_of_revolution_creator_hpp
#define eli_geom_surface_piecewise_body_of_revolution_creator_hpp

#include <list>
#include <iterator>

#include "eli/code_eli.hpp"

#include "eli/util/tolerance.hpp"

#include "eli/geom/curve/piecewise.hpp"
#include "eli/geom/curve/piecewise_creator.hpp"

#include "eli/geom/surface/piecewise.hpp"
#include "eli/geom/surface/bezier.hpp"

namespace eli
{
  namespace geom
  {
    namespace surface
    {
      template<typename data__, unsigned short dim__, typename tol__>
      bool create_body_of_revolution(piecewise<bezier, data__, dim__, tol__> &ps,
                                     const eli::geom::curve::piecewise<eli::geom::curve::bezier, data__, dim__, tol__> &pc,
                                     int axis, bool outward_normal, bool match_uparm = false)
      {
        typedef piecewise<bezier, data__, dim__, tol__> piecewise_surface_type;
        typedef eli::geom::curve::piecewise<eli::geom::curve::bezier, data__, dim__, tol__> piecewise_curve_type;
        typedef eli::geom::curve::piecewise_circle_creator<data__, dim__, tol__> circle_creator_type;
        typedef typename piecewise_curve_type::curve_type curve_type;
        typedef typename piecewise_surface_type::surface_type surface_type;
        typedef typename curve_type::point_type point_type;
        typedef typename curve_type::data_type data_type;
        typedef typename curve_type::index_type index_type;

        curve_type c, arc;
        surface_type s[4];
        piecewise_curve_type pc_circle;
        point_type origin, normal, start;
        data_type du, dv;
        index_type i, j, pp, qq, nu=pc.number_segments(), nv=4, udim, vdim;

        // resize the surface
        if ( match_uparm )
        {
          vector<data_type> umap, du;
          pc.get_pmap( umap );

          for ( i = 0; i < nu; i++ )
          {
            du.push_back( umap[ i + 1 ] - umap[ i ] );
          }

          ps.init_uv( du.begin(), du.end(), nv, 1, umap[0] );
        }
        else
        {
          ps.init_uv(nu, nv);
        }

        // set the axis of rotation
        switch(axis)
        {
          case(0):
          {
            normal << 1, 0, 0;
            break;
          }
          case(1):
          {
            normal << 0, 1, 0;
            break;
          }
          case(2):
          {
            normal << 0, 0, 1;
            break;
          }
          default:
          {
            assert(false);
            return false;
          }
        }
        if (outward_normal)
        {
          normal*=-1;
        }

        // cycle through each curve segment
        circle_creator_type circle_creator;
        for (pp=0; pp<nu; ++pp)
        {
          // resize the surface patch
          udim=c.dimension();
          vdim=3;
          pc.get(c, du, pp);
          s[0].resize(udim, vdim);
          s[1].resize(udim, vdim);
          s[2].resize(udim, vdim);
          s[3].resize(udim, vdim);

          // cycle through each control point in current curve and create patch control points
          for (i=0; i<=udim; ++i)
          {
            // set up the vectors for this circle
            start=c.get_control_point(i);
            origin=normal.dot(start)*normal;

            // get the circle
            circle_creator.set(start, origin, normal);
            if (!circle_creator.create(pc_circle))
            {
              assert(false);
              return false;
            }

            // for each segment of circle set the control points
            for (qq=0; qq<4; ++qq)
            {
              pc_circle.get(arc, dv, qq);
              for (j=0; j<4; ++j)
              {
                s[qq].set_control_point(arc.get_control_point(j), i, j);
              }
            }
          }

          // set the surface patches
          for (qq=0; qq<4; ++qq)
          {
            ps.set(s[qq], pp, qq);
          }
        }

        return true;
      }
    }
  }
}
#endif
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmlanchorbindingproxy.h"
#include <qmlanchors.h>
#include <nodeabstractproperty.h>
#include <nodeinstance.h>
#include <QDebug>

namespace QmlDesigner {

class ModelNode;
class NodeState;

namespace Internal {

QmlAnchorBindingProxy::QmlAnchorBindingProxy(QObject *parent) :
        QObject(parent)
{
}

QmlAnchorBindingProxy::~QmlAnchorBindingProxy()
{
}

void QmlAnchorBindingProxy::setup(const QmlItemNode &fxItemNode)
{
    m_fxItemNode = fxItemNode;

    m_verticalTarget = m_horizontalTarget = m_topTarget = m_bottomTarget = m_leftTarget = m_rightTarget = m_fxItemNode.modelNode().parentProperty().parentModelNode();

    if (topAnchored())
        m_topTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::Top).qmlItemNode();

    if (bottomAnchored())
        m_bottomTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::Bottom).qmlItemNode();

    if (leftAnchored())
        m_leftTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::Left).qmlItemNode();

    if (rightAnchored())
        m_rightTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::Right).qmlItemNode();

    if (verticalCentered())
        m_verticalTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::VerticalCenter).qmlItemNode();

    if (horizontalCentered())
        m_horizontalTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::HorizontalCenter).qmlItemNode();

    emit parentChanged();
    emit topAnchorChanged();
    emit bottomAnchorChanged();
    emit leftAnchorChanged();
    emit rightAnchorChanged();
    emit centeredHChanged();
    emit centeredVChanged();
    emit anchorsChanged();

    if (m_fxItemNode.hasNodeParent()) {
        emit itemNodeChanged();
        emit topTargetChanged();
        emit bottomTargetChanged();
        emit leftTargetChanged();
        emit rightTargetChanged();
        emit verticalTargetChanged();
        emit horizontalTargetChanged();
    }
}

bool QmlAnchorBindingProxy::hasParent()
{
    return m_fxItemNode.isValid() && m_fxItemNode.hasNodeParent();
}

bool QmlAnchorBindingProxy::topAnchored()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Top);
}

bool QmlAnchorBindingProxy::bottomAnchored()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Bottom);
}

bool QmlAnchorBindingProxy::leftAnchored()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Left);
}

bool QmlAnchorBindingProxy::rightAnchored()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Right);
}

bool QmlAnchorBindingProxy::hasAnchors()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchors();
}

void QmlAnchorBindingProxy::setTopTarget(const QVariant &target)
{
    QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_topTarget)
        return;

    m_topTarget = newTarget;
    calcTopMargin();

    emit topTargetChanged();
}

void QmlAnchorBindingProxy::setBottomTarget(const QVariant &target)
{
    QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_bottomTarget)
        return;

    m_bottomTarget = newTarget;
    calcBottomMargin();

    emit bottomTargetChanged();
}

void QmlAnchorBindingProxy::setLeftTarget(const QVariant &target)
{
    QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_leftTarget)
        return;

    m_leftTarget = newTarget;
    calcLeftMargin();

    emit leftTargetChanged();
}

void QmlAnchorBindingProxy::setRightTarget(const QVariant &target)
{
    QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_rightTarget)
        return;

    m_rightTarget = newTarget;
    calcRightMargin();

    emit rightTargetChanged();
}

void QmlAnchorBindingProxy::setVerticalTarget(const QVariant &target)
{
     QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_verticalTarget)
        return;

    m_verticalTarget = newTarget;
    m_fxItemNode.anchors().setAnchor(AnchorLine::VerticalCenter, m_verticalTarget, AnchorLine::VerticalCenter);

    emit verticalTargetChanged();
}

void QmlAnchorBindingProxy::setHorizontalTarget(const QVariant &target)
{
    QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_horizontalTarget)
        return;

    m_horizontalTarget = newTarget;
    m_fxItemNode.anchors().setAnchor(AnchorLine::HorizontalCenter, m_horizontalTarget, AnchorLine::HorizontalCenter);

    emit horizontalTargetChanged();
}

void QmlAnchorBindingProxy::resetLayout() {
        m_fxItemNode.anchors().removeAnchors();
        m_fxItemNode.anchors().removeMargins();

        emit topAnchorChanged();
        emit bottomAnchorChanged();
        emit leftAnchorChanged();
        emit rightAnchorChanged();
        emit anchorsChanged();
    }

void QmlAnchorBindingProxy::setBottomAnchor(bool anchor)
{
    if (!m_fxItemNode.hasNodeParent())
        return;

    if (bottomAnchored() == anchor)
        return;

    if (!anchor) {
        removeBottomAnchor();
    } else {
        calcBottomMargin();
    }
    emit bottomAnchorChanged();

    if (hasAnchors() != anchor)
        emit anchorsChanged();
}

void QmlAnchorBindingProxy::setLeftAnchor(bool anchor)
{
    if (!m_fxItemNode.hasNodeParent())
        return;

    if (leftAnchored() == anchor)
        return;

    if (!anchor) {
        removeLeftAnchor();
    } else {
        calcLeftMargin();
    }
    emit leftAnchorChanged();
    if (hasAnchors() != anchor)
        emit anchorsChanged();
}

void QmlAnchorBindingProxy::setRightAnchor(bool anchor)
{
    if (!m_fxItemNode.hasNodeParent())
        return;

    if (rightAnchored() == anchor)
        return;

    if (!anchor) {
        removeRightAnchor();
    } else {
        calcRightMargin();
    }
    emit rightAnchorChanged();
    if (hasAnchors() != anchor)
        emit anchorsChanged();
}
 QRectF QmlAnchorBindingProxy::parentBoundingBox()
{
    if (m_fxItemNode.hasInstanceParent())
        return m_fxItemNode.instanceParent().toQmlItemNode().instanceBoundingRect();

    return QRect();
}

QRectF QmlAnchorBindingProxy::boundingBox(QmlItemNode node)
{
    if (node.isValid())
        return node.instanceTransform().mapRect(node.instanceBoundingRect());

    return QRect();
}

QRectF QmlAnchorBindingProxy::transformedBoundingBox()
{
    return m_fxItemNode.instanceTransform().mapRect(m_fxItemNode.instanceBoundingRect());
}

void QmlAnchorBindingProxy::calcTopMargin()
{
    if (m_topTarget == m_fxItemNode.modelNode().parentProperty().parentModelNode()) {
        qreal topMargin = transformedBoundingBox().top() - parentBoundingBox().top();
        m_fxItemNode.anchors().setMargin( AnchorLine::Top, topMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Top, m_topTarget, AnchorLine::Top);
    } else {
        qDebug() << boundingBox(m_fxItemNode).top();
        qDebug() << boundingBox(m_topTarget).bottom();
        qreal topMargin = boundingBox(m_fxItemNode).top() - boundingBox(m_topTarget).bottom();
        m_fxItemNode.anchors().setMargin( AnchorLine::Top, topMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Top, m_topTarget, AnchorLine::Bottom);
    }
}

void QmlAnchorBindingProxy::calcBottomMargin()
{
    if (m_bottomTarget == m_fxItemNode.modelNode().parentProperty().parentModelNode()) {
        qreal bottomMargin =  parentBoundingBox().bottom() - transformedBoundingBox().bottom();
        m_fxItemNode.anchors().setMargin( AnchorLine::Bottom, bottomMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Bottom, m_bottomTarget, AnchorLine::Bottom);
    } else {
        qreal bottomMargin = boundingBox(m_fxItemNode).bottom() - boundingBox(m_rightTarget).top();
        m_fxItemNode.anchors().setMargin( AnchorLine::Bottom, bottomMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Bottom, m_bottomTarget, AnchorLine::Top);
    }
}

void QmlAnchorBindingProxy::calcLeftMargin()
{
    if (m_leftTarget == m_fxItemNode.modelNode().parentProperty().parentModelNode()) {
        qreal leftMargin = transformedBoundingBox().left() - parentBoundingBox().left();
        m_fxItemNode.anchors().setMargin(AnchorLine::Left, leftMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Left, m_leftTarget, AnchorLine::Left);
    } else {
        qreal leftMargin = boundingBox(m_fxItemNode).left() - boundingBox(m_leftTarget).right();
        m_fxItemNode.anchors().setMargin( AnchorLine::Left, leftMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Left, m_leftTarget, AnchorLine::Right);
    }
}

void QmlAnchorBindingProxy::calcRightMargin()
{
    if (m_rightTarget == m_fxItemNode.modelNode().parentProperty().parentModelNode()) {
        qreal rightMargin = transformedBoundingBox().right() - parentBoundingBox().right();
        m_fxItemNode.anchors().setMargin( AnchorLine::Right, rightMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Right, m_rightTarget, AnchorLine::Right);
    } else {
        qreal rightMargin = boundingBox(m_rightTarget).left() - boundingBox(m_fxItemNode).right();
        m_fxItemNode.anchors().setMargin( AnchorLine::Right, rightMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Right, m_rightTarget, AnchorLine::Left);
    }
}

void QmlAnchorBindingProxy::setTopAnchor(bool anchor)
{
    if (!m_fxItemNode.hasNodeParent())
        return ;

    if (topAnchored() == anchor)
        return;

    if (!anchor) {
        removeTopAnchor();
    } else {
        calcTopMargin();
    }
    emit topAnchorChanged();
    if (hasAnchors() != anchor)
        emit anchorsChanged();
}

void QmlAnchorBindingProxy::removeTopAnchor() {
    m_fxItemNode.anchors().removeAnchor(AnchorLine::Top);
    m_fxItemNode.anchors().removeMargin(AnchorLine::Top);
}

void QmlAnchorBindingProxy::removeBottomAnchor() {
    m_fxItemNode.anchors().removeAnchor(AnchorLine::Bottom);
    m_fxItemNode.anchors().removeMargin(AnchorLine::Bottom);
}

void QmlAnchorBindingProxy::removeLeftAnchor() {
    m_fxItemNode.anchors().removeAnchor(AnchorLine::Left);
    m_fxItemNode.anchors().removeMargin(AnchorLine::Left);
}

void QmlAnchorBindingProxy::removeRightAnchor() {
    m_fxItemNode.anchors().removeAnchor(AnchorLine::Right);
    m_fxItemNode.anchors().removeMargin(AnchorLine::Right);
}

void QmlAnchorBindingProxy::setVerticalCentered(bool centered)
{
    if (!m_fxItemNode.hasNodeParent())
        return ;

    if (verticalCentered() == centered)
        return;

    if (!centered) {
        m_fxItemNode.anchors().removeAnchor(AnchorLine::VerticalCenter);
        m_fxItemNode.anchors().removeMargin(AnchorLine::VerticalCenter);
    } else {
        m_fxItemNode.anchors().setAnchor(AnchorLine::VerticalCenter, m_fxItemNode.modelNode().parentProperty().parentModelNode(), AnchorLine::VerticalCenter);
    }
    emit centeredVChanged();
}

void QmlAnchorBindingProxy::setHorizontalCentered(bool centered)
{
    if (!m_fxItemNode.hasNodeParent())
        return ;

    if (horizontalCentered() == centered)
        return;

    if (!centered) {
        m_fxItemNode.anchors().removeAnchor(AnchorLine::HorizontalCenter);
        m_fxItemNode.anchors().removeMargin(AnchorLine::HorizontalCenter);
    } else {
        m_fxItemNode.anchors().setAnchor(AnchorLine::HorizontalCenter, m_fxItemNode.modelNode().parentProperty().parentModelNode(), AnchorLine::HorizontalCenter);
    }
    emit centeredHChanged();
}

bool QmlAnchorBindingProxy::verticalCentered()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::VerticalCenter);
}

bool QmlAnchorBindingProxy::horizontalCentered()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::HorizontalCenter);
}

void QmlAnchorBindingProxy::fill()
{
    m_fxItemNode.anchors().fill();

    setHorizontalCentered(false);
    setVerticalCentered(false);

    m_fxItemNode.anchors().setMargin(AnchorLine::Right, 0);
    m_fxItemNode.anchors().setMargin(AnchorLine::Left, 0);
    m_fxItemNode.anchors().setMargin(AnchorLine::Top, 0);
    m_fxItemNode.anchors().setMargin(AnchorLine::Bottom, 0);

    emit topAnchorChanged();
    emit bottomAnchorChanged();
    emit leftAnchorChanged();
    emit rightAnchorChanged();
    emit anchorsChanged();
}

} // namespace Internal
} // namespace QmlDesigner

<commit_msg>QmlDesigner.propertyEditor: fixes bug in marging calulation<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "qmlanchorbindingproxy.h"
#include <qmlanchors.h>
#include <nodeabstractproperty.h>
#include <nodeinstance.h>
#include <QDebug>

namespace QmlDesigner {

class ModelNode;
class NodeState;

namespace Internal {

QmlAnchorBindingProxy::QmlAnchorBindingProxy(QObject *parent) :
        QObject(parent)
{
}

QmlAnchorBindingProxy::~QmlAnchorBindingProxy()
{
}

void QmlAnchorBindingProxy::setup(const QmlItemNode &fxItemNode)
{
    m_fxItemNode = fxItemNode;

    m_verticalTarget = m_horizontalTarget = m_topTarget = m_bottomTarget = m_leftTarget = m_rightTarget = m_fxItemNode.modelNode().parentProperty().parentModelNode();

    if (topAnchored())
        m_topTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::Top).qmlItemNode();

    if (bottomAnchored())
        m_bottomTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::Bottom).qmlItemNode();

    if (leftAnchored())
        m_leftTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::Left).qmlItemNode();

    if (rightAnchored())
        m_rightTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::Right).qmlItemNode();

    if (verticalCentered())
        m_verticalTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::VerticalCenter).qmlItemNode();

    if (horizontalCentered())
        m_horizontalTarget = m_fxItemNode.anchors().instanceAnchor(AnchorLine::HorizontalCenter).qmlItemNode();

    emit parentChanged();
    emit topAnchorChanged();
    emit bottomAnchorChanged();
    emit leftAnchorChanged();
    emit rightAnchorChanged();
    emit centeredHChanged();
    emit centeredVChanged();
    emit anchorsChanged();

    if (m_fxItemNode.hasNodeParent()) {
        emit itemNodeChanged();
        emit topTargetChanged();
        emit bottomTargetChanged();
        emit leftTargetChanged();
        emit rightTargetChanged();
        emit verticalTargetChanged();
        emit horizontalTargetChanged();
    }
}

bool QmlAnchorBindingProxy::hasParent()
{
    return m_fxItemNode.isValid() && m_fxItemNode.hasNodeParent();
}

bool QmlAnchorBindingProxy::topAnchored()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Top);
}

bool QmlAnchorBindingProxy::bottomAnchored()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Bottom);
}

bool QmlAnchorBindingProxy::leftAnchored()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Left);
}

bool QmlAnchorBindingProxy::rightAnchored()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::Right);
}

bool QmlAnchorBindingProxy::hasAnchors()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchors();
}

void QmlAnchorBindingProxy::setTopTarget(const QVariant &target)
{
    QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_topTarget)
        return;

    m_topTarget = newTarget;
    calcTopMargin();

    emit topTargetChanged();
}

void QmlAnchorBindingProxy::setBottomTarget(const QVariant &target)
{
    QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_bottomTarget)
        return;

    m_bottomTarget = newTarget;
    calcBottomMargin();

    emit bottomTargetChanged();
}

void QmlAnchorBindingProxy::setLeftTarget(const QVariant &target)
{
    QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_leftTarget)
        return;

    m_leftTarget = newTarget;
    calcLeftMargin();

    emit leftTargetChanged();
}

void QmlAnchorBindingProxy::setRightTarget(const QVariant &target)
{
    QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_rightTarget)
        return;

    m_rightTarget = newTarget;
    calcRightMargin();

    emit rightTargetChanged();
}

void QmlAnchorBindingProxy::setVerticalTarget(const QVariant &target)
{
     QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_verticalTarget)
        return;

    m_verticalTarget = newTarget;
    m_fxItemNode.anchors().setAnchor(AnchorLine::VerticalCenter, m_verticalTarget, AnchorLine::VerticalCenter);

    emit verticalTargetChanged();
}

void QmlAnchorBindingProxy::setHorizontalTarget(const QVariant &target)
{
    QmlItemNode newTarget(target.value<ModelNode>());

    if (newTarget == m_horizontalTarget)
        return;

    m_horizontalTarget = newTarget;
    m_fxItemNode.anchors().setAnchor(AnchorLine::HorizontalCenter, m_horizontalTarget, AnchorLine::HorizontalCenter);

    emit horizontalTargetChanged();
}

void QmlAnchorBindingProxy::resetLayout() {
        m_fxItemNode.anchors().removeAnchors();
        m_fxItemNode.anchors().removeMargins();

        emit topAnchorChanged();
        emit bottomAnchorChanged();
        emit leftAnchorChanged();
        emit rightAnchorChanged();
        emit anchorsChanged();
    }

void QmlAnchorBindingProxy::setBottomAnchor(bool anchor)
{
    if (!m_fxItemNode.hasNodeParent())
        return;

    if (bottomAnchored() == anchor)
        return;

    if (!anchor) {
        removeBottomAnchor();
    } else {
        calcBottomMargin();
    }
    emit bottomAnchorChanged();

    if (hasAnchors() != anchor)
        emit anchorsChanged();
}

void QmlAnchorBindingProxy::setLeftAnchor(bool anchor)
{
    if (!m_fxItemNode.hasNodeParent())
        return;

    if (leftAnchored() == anchor)
        return;

    if (!anchor) {
        removeLeftAnchor();
    } else {
        calcLeftMargin();
    }
    emit leftAnchorChanged();
    if (hasAnchors() != anchor)
        emit anchorsChanged();
}

void QmlAnchorBindingProxy::setRightAnchor(bool anchor)
{
    if (!m_fxItemNode.hasNodeParent())
        return;

    if (rightAnchored() == anchor)
        return;

    if (!anchor) {
        removeRightAnchor();
    } else {
        calcRightMargin();
    }
    emit rightAnchorChanged();
    if (hasAnchors() != anchor)
        emit anchorsChanged();
}
 QRectF QmlAnchorBindingProxy::parentBoundingBox()
{
    if (m_fxItemNode.hasInstanceParent())
        return m_fxItemNode.instanceParent().toQmlItemNode().instanceBoundingRect();

    return QRect();
}

QRectF QmlAnchorBindingProxy::boundingBox(QmlItemNode node)
{
    if (node.isValid())
        return node.instanceTransform().mapRect(node.instanceBoundingRect());

    return QRect();
}

QRectF QmlAnchorBindingProxy::transformedBoundingBox()
{
    return m_fxItemNode.instanceTransform().mapRect(m_fxItemNode.instanceBoundingRect());
}

void QmlAnchorBindingProxy::calcTopMargin()
{
    if (m_topTarget == m_fxItemNode.modelNode().parentProperty().parentModelNode()) {
        qreal topMargin = transformedBoundingBox().top() - parentBoundingBox().top();
        m_fxItemNode.anchors().setMargin( AnchorLine::Top, topMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Top, m_topTarget, AnchorLine::Top);
    } else {
        qDebug() << boundingBox(m_fxItemNode).top();
        qDebug() << boundingBox(m_topTarget).bottom();
        qreal topMargin = boundingBox(m_fxItemNode).top() - boundingBox(m_topTarget).bottom();
        m_fxItemNode.anchors().setMargin( AnchorLine::Top, topMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Top, m_topTarget, AnchorLine::Bottom);
    }
}

void QmlAnchorBindingProxy::calcBottomMargin()
{
    if (m_bottomTarget == m_fxItemNode.modelNode().parentProperty().parentModelNode()) {
        qreal bottomMargin =  parentBoundingBox().bottom() - transformedBoundingBox().bottom();
        m_fxItemNode.anchors().setMargin( AnchorLine::Bottom, bottomMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Bottom, m_bottomTarget, AnchorLine::Bottom);
    } else {
        qreal bottomMargin = boundingBox(m_fxItemNode).bottom() - boundingBox(m_rightTarget).top();
        m_fxItemNode.anchors().setMargin( AnchorLine::Bottom, bottomMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Bottom, m_bottomTarget, AnchorLine::Top);
    }
}

void QmlAnchorBindingProxy::calcLeftMargin()
{
    if (m_leftTarget == m_fxItemNode.modelNode().parentProperty().parentModelNode()) {
        qreal leftMargin = transformedBoundingBox().left() - parentBoundingBox().left();
        m_fxItemNode.anchors().setMargin(AnchorLine::Left, leftMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Left, m_leftTarget, AnchorLine::Left);
    } else {
        qreal leftMargin = boundingBox(m_fxItemNode).left() - boundingBox(m_leftTarget).right();
        m_fxItemNode.anchors().setMargin( AnchorLine::Left, leftMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Left, m_leftTarget, AnchorLine::Right);
    }
}

void QmlAnchorBindingProxy::calcRightMargin()
{
    if (m_rightTarget == m_fxItemNode.modelNode().parentProperty().parentModelNode()) {
        qreal rightMargin = parentBoundingBox().right() - transformedBoundingBox().right();
        m_fxItemNode.anchors().setMargin( AnchorLine::Right, rightMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Right, m_rightTarget, AnchorLine::Right);
    } else {
        qreal rightMargin = boundingBox(m_rightTarget).left() - boundingBox(m_fxItemNode).right();
        m_fxItemNode.anchors().setMargin( AnchorLine::Right, rightMargin);
        m_fxItemNode.anchors().setAnchor(AnchorLine::Right, m_rightTarget, AnchorLine::Left);
    }
}

void QmlAnchorBindingProxy::setTopAnchor(bool anchor)
{
    if (!m_fxItemNode.hasNodeParent())
        return ;

    if (topAnchored() == anchor)
        return;

    if (!anchor) {
        removeTopAnchor();
    } else {
        calcTopMargin();
    }
    emit topAnchorChanged();
    if (hasAnchors() != anchor)
        emit anchorsChanged();
}

void QmlAnchorBindingProxy::removeTopAnchor() {
    m_fxItemNode.anchors().removeAnchor(AnchorLine::Top);
    m_fxItemNode.anchors().removeMargin(AnchorLine::Top);
}

void QmlAnchorBindingProxy::removeBottomAnchor() {
    m_fxItemNode.anchors().removeAnchor(AnchorLine::Bottom);
    m_fxItemNode.anchors().removeMargin(AnchorLine::Bottom);
}

void QmlAnchorBindingProxy::removeLeftAnchor() {
    m_fxItemNode.anchors().removeAnchor(AnchorLine::Left);
    m_fxItemNode.anchors().removeMargin(AnchorLine::Left);
}

void QmlAnchorBindingProxy::removeRightAnchor() {
    m_fxItemNode.anchors().removeAnchor(AnchorLine::Right);
    m_fxItemNode.anchors().removeMargin(AnchorLine::Right);
}

void QmlAnchorBindingProxy::setVerticalCentered(bool centered)
{
    if (!m_fxItemNode.hasNodeParent())
        return ;

    if (verticalCentered() == centered)
        return;

    if (!centered) {
        m_fxItemNode.anchors().removeAnchor(AnchorLine::VerticalCenter);
        m_fxItemNode.anchors().removeMargin(AnchorLine::VerticalCenter);
    } else {
        m_fxItemNode.anchors().setAnchor(AnchorLine::VerticalCenter, m_fxItemNode.modelNode().parentProperty().parentModelNode(), AnchorLine::VerticalCenter);
    }
    emit centeredVChanged();
}

void QmlAnchorBindingProxy::setHorizontalCentered(bool centered)
{
    if (!m_fxItemNode.hasNodeParent())
        return ;

    if (horizontalCentered() == centered)
        return;

    if (!centered) {
        m_fxItemNode.anchors().removeAnchor(AnchorLine::HorizontalCenter);
        m_fxItemNode.anchors().removeMargin(AnchorLine::HorizontalCenter);
    } else {
        m_fxItemNode.anchors().setAnchor(AnchorLine::HorizontalCenter, m_fxItemNode.modelNode().parentProperty().parentModelNode(), AnchorLine::HorizontalCenter);
    }
    emit centeredHChanged();
}

bool QmlAnchorBindingProxy::verticalCentered()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::VerticalCenter);
}

bool QmlAnchorBindingProxy::horizontalCentered()
{
    return m_fxItemNode.isValid() && m_fxItemNode.anchors().instanceHasAnchor(AnchorLine::HorizontalCenter);
}

void QmlAnchorBindingProxy::fill()
{
    m_fxItemNode.anchors().fill();

    setHorizontalCentered(false);
    setVerticalCentered(false);

    m_fxItemNode.anchors().setMargin(AnchorLine::Right, 0);
    m_fxItemNode.anchors().setMargin(AnchorLine::Left, 0);
    m_fxItemNode.anchors().setMargin(AnchorLine::Top, 0);
    m_fxItemNode.anchors().setMargin(AnchorLine::Bottom, 0);

    emit topAnchorChanged();
    emit bottomAnchorChanged();
    emit leftAnchorChanged();
    emit rightAnchorChanged();
    emit anchorsChanged();
}

} // namespace Internal
} // namespace QmlDesigner

<|endoftext|>


<commit_before>#include "card.h"
#include "localization.h"
#include <string>
#include <stdexcept>
#include <sstream>

std::string Card::_outputFormat = DEFAULT_OUTPUT_FORMAT;

Card::Card()
{
	_name = CnNone;
	_suit = CsNone;
	_score = 0;
	_outputFormat = DEFAULT_OUTPUT_FORMAT;
}

Card::Card(CardSuit suit, CardName name, unsigned int score)
{
	_name = name;
	_suit = suit;
	SetScore(score);
	_outputFormat = DEFAULT_OUTPUT_FORMAT;
}

std::string Card::GetFormattedName() const
{
	if (!IsValid()) return "";
	std::string temp(_outputFormat);

	std::size_t pos = temp.find('N');
    temp.erase(temp.begin()+pos);
	temp.insert(pos, GetStr((Strings)(_name + 6)));

	pos = temp.find('S');
    temp.erase(temp.begin()+pos);
    temp.insert(pos, GetStr((Strings)(_name + 1)));

	return temp;
}

void Card::SetScore(unsigned int score)
{
	if (score >= MIN_SCORE && score <= MAX_SCORE)
		_score = score;
	else
	{
		throw std::logic_error( "Invalid Score!" );

	}
}
<commit_msg>Fixed ShowCard() in card.cpp<commit_after>#include "card.h"
#include "localization.h"
#include <string>
#include <stdexcept>
#include <sstream>

std::string Card::_outputFormat = DEFAULT_OUTPUT_FORMAT;

Card::Card()
{
	_name = CnNone;
	_suit = CsNone;
	_score = 0;
	_outputFormat = DEFAULT_OUTPUT_FORMAT;
}

Card::Card(CardSuit suit, CardName name, unsigned int score)
{
	_name = name;
	_suit = suit;
	SetScore(score);
	_outputFormat = DEFAULT_OUTPUT_FORMAT;
}

std::string Card::GetFormattedName() const
{
	if (!IsValid()) return "";
	std::string temp(_outputFormat);

	std::size_t pos = temp.find('N');
    temp.erase(temp.begin()+pos);
	temp.insert(pos, GetStr((Strings)(_name + 6)));

	pos = temp.find('S');
    temp.erase(temp.begin()+pos);
    temp.insert(pos, GetStr((Strings)(_suit + 1)));

	return temp;
}

void Card::SetScore(unsigned int score)
{
	if (score >= MIN_SCORE && score <= MAX_SCORE)
		_score = score;
	else
	{
		throw std::logic_error( "Invalid Score!" );

	}
}
<|endoftext|>


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

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

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

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

=========================================================================*/

#include "itkImageRegistrationMethod.h"
#include "itkTranslationTransform.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkGradientDescentOptimizer.h"

/**
 *  This program test one instantiation of the itk::ImageRegistrationMethod class
 *
 *  Only typedef are tested in this file.
 */

int itkImageRegistrationMethodTest_3(int, char**)
{

  bool pass = true;

  const unsigned int dimension = 3;

  // Fixed Image Type
  typedef itk::Image<float,dimension>                    FixedImageType;

  // Moving Image Type
  typedef itk::Image<char,dimension>                     MovingImageType;

  // Transform Type
  typedef itk::TranslationTransform< double,dimension >  TransformType;

  // Optimizer Type
  typedef itk::GradientDescentOptimizer                  OptimizerType;

  // Metric Type
  typedef itk::MeanSquaresImageToImageMetric<
                                    FixedImageType,
                                    MovingImageType >    MetricType;

  // Interpolation technique
  typedef itk:: LinearInterpolateImageFunction<
                                    MovingImageType,
                                    double          >    InterpolatorType;

  // Registration Method
  typedef itk::ImageRegistrationMethod<
                                    FixedImageType,
                                    MovingImageType >    RegistrationType;

  MetricType::Pointer         metric        = MetricType::New();
  TransformType::Pointer      transform     = TransformType::New();
  OptimizerType::Pointer      optimizer     = OptimizerType::New();
  TransformType::Pointer      trasform      = TransformType::New();
  FixedImageType::Pointer     fixedImage    = FixedImageType::New();
  MovingImageType::Pointer    movingImage   = MovingImageType::New();
  InterpolatorType::Pointer   interpolator  = InterpolatorType::New();
  RegistrationType::Pointer   registration  = RegistrationType::New();

  registration->SetMetric(        metric        );
  registration->SetOptimizer(     optimizer     );
  registration->SetTransform(     transform     );
  registration->SetFixedImage(    fixedImage    );
  registration->SetMovingImage(   movingImage   );
  registration->SetInterpolator(  interpolator  );

  if( !pass )
    {
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;

}
<commit_msg>ENH: A full registration is performed now. Parameters are tunned.<commit_after>/*=========================================================================

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

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

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

=========================================================================*/

#include "itkImageRegistrationMethod.h"
#include "itkTranslationTransform.h"
#include "itkMeanSquaresImageToImageMetric.h"
#include "itkLinearInterpolateImageFunction.h"
#include "itkGradientDescentOptimizer.h"
#include "itkCommandIterationUpdate.h"

#include "itkImageRegistrationMethodImageSource.h"

/**
 *  This program tests one instantiation of the itk::ImageRegistrationMethod class
 *
 *
 */

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

  bool pass = true;

  const unsigned int dimension = 2;

  // Fixed Image Type
  typedef itk::Image<float,dimension>               FixedImageType;

  // Moving Image Type
  typedef itk::Image<float,dimension>               MovingImageType;

  // Size Type
  typedef MovingImageType::SizeType                 SizeType;

  // ImageSource
  typedef itk::testhelper::ImageRegistrationMethodImageSource<
                                  FixedImageType::PixelType,
                                  MovingImageType::PixelType,
                                  dimension >         ImageSourceType;
  // Transform Type
  typedef itk::TranslationTransform< double, dimension > TransformType;
  typedef TransformType::ParametersType             ParametersType;

  // Optimizer Type
  typedef itk::GradientDescentOptimizer                  OptimizerType;

  // Metric Type
  typedef itk::MeanSquaresImageToImageMetric<
                                    FixedImageType,
                                    MovingImageType >    MetricType;

  // Interpolation technique
  typedef itk:: LinearInterpolateImageFunction<
                                    MovingImageType,
                                    double >             InterpolatorType;

  // Registration Method
  typedef itk::ImageRegistrationMethod<
                                    FixedImageType,
                                    MovingImageType >    RegistrationType;

  typedef itk::CommandIterationUpdate<
                                  OptimizerType >    CommandIterationType;

  MetricType::Pointer         metric        = MetricType::New();
  TransformType::Pointer      transform     = TransformType::New();
  OptimizerType::Pointer      optimizer     = OptimizerType::New();
  TransformType::Pointer      trasform      = TransformType::New();
  InterpolatorType::Pointer   interpolator  = InterpolatorType::New();
  RegistrationType::Pointer   registration  = RegistrationType::New();

  ImageSourceType::Pointer    imageSource   = ImageSourceType::New();

  SizeType size;
  size[0] = 100;
  size[1] = 100;

  imageSource->GenerateImages( size );

  FixedImageType::ConstPointer     fixedImage    = imageSource->GetFixedImage();
  MovingImageType::ConstPointer    movingImage   = imageSource->GetMovingImage();

  //
  // Connect all the components required for Registratio
  //
  registration->SetMetric(        metric        );
  registration->SetOptimizer(     optimizer     );
  registration->SetTransform(     transform     );
  registration->SetFixedImage(    fixedImage    );
  registration->SetMovingImage(   movingImage   );
  registration->SetInterpolator(  interpolator  );

  // Select the Region of Interest over which the Metric will be computed
  // Registration time will be proportional to the number of pixels in this region.
  metric->SetFixedImageRegion( fixedImage->GetBufferedRegion() );

  // Instantiate an Observer to report the progress of the Optimization
  CommandIterationType::Pointer iterationCommand = CommandIterationType::New();
  iterationCommand->SetOptimizer(  optimizer.GetPointer() );

  // Scale the translation components of the Transform in the Optimizer
  OptimizerType::ScalesType scales( transform->GetNumberOfParameters() );
  scales.Fill( 1.0 );

  unsigned long   numberOfIterations =   50;
  double          translationScale   =  1.0;
  double          learningRate       = 1e-2;

  if( argc > 1 )
    {
    numberOfIterations = atol( argv[1] );
    std::cout << "numberOfIterations = " << numberOfIterations << std::endl;
    }
  if( argc > 2 )
    {
    translationScale = atof( argv[2] );
    std::cout << "translationScale = " << translationScale << std::endl;
    }
  if( argc > 3 )
    {
    learningRate = atof( argv[3] );
    std::cout << "learningRate = " << learningRate << std::endl;
    }

  for( unsigned int i=0; i<dimension; i++)
    {
    scales[ i + dimension * dimension ] = translationScale;
    }

  optimizer->SetScales( scales );
  optimizer->SetLearningRate( learningRate );
  optimizer->SetNumberOfIterations( numberOfIterations );

  // Start from an Identity transform (in a normal case, the user
  // can probably provide a better guess than the identity...
  transform->SetIdentity();
  registration->SetInitialTransformParameters( transform->GetParameters() );

  // Initialize the internal connections of the registration method.
  // This can potentially throw an exception
  try
    {
    registration->StartRegistration();
    }
  catch( itk::ExceptionObject & e )
    {
    std::cerr << e << std::endl;
    pass = false;
    }

  ParametersType actualParameters = imageSource->GetActualParameters();
  ParametersType finalParameters  = registration->GetLastTransformParameters();

  const unsigned int numbeOfParameters = actualParameters.Size();

  const double tolerance = 1.0;  // equivalent to 1 pixel.

  for(unsigned int i=0; i<numbeOfParameters; i++)
    {
    // the parameters are negated in order to get the inverse transformation.
    // this only works for comparing translation parameters....
    std::cout << finalParameters[i] << " == " << -actualParameters[i] << std::endl;
    if( fabs ( finalParameters[i] - (-actualParameters[i]) ) > tolerance )
      {
      std::cout << "Tolerance exceeded at component " << i << std::endl;
      pass = false;
      }
    }

  if( !pass )
    {
    std::cout << "Test FAILED." << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "Test PASSED." << std::endl;
  return EXIT_SUCCESS;

}
<|endoftext|>