示例#1
0
void RenderContainer::addChild(RenderObject* newChild, RenderObject* beforeChild)
{
    bool needsTable = false;

    if (newChild->isListItem())
        updateListMarkerNumbers(beforeChild ? beforeChild : m_lastChild);
    else if (newChild->isTableCol() && newChild->style()->display() == TABLE_COLUMN_GROUP)
        needsTable = !isTable();
    else if (newChild->isRenderBlock() && newChild->style()->display() == TABLE_CAPTION)
        needsTable = !isTable();
    else if (newChild->isTableSection())
        needsTable = !isTable();
    else if (newChild->isTableRow())
        needsTable = !isTableSection();
    else if (newChild->isTableCell()) {
        needsTable = !isTableRow();
        // I'm not 100% sure this is the best way to fix this, but without this
        // change we recurse infinitely when trying to render the CSS2 test page:
        // http://www.bath.ac.uk/%7Epy8ieh/internet/eviltests/htmlbodyheadrendering2.html.
        // See Radar 2925291.
        if (needsTable && isTableCell() && !m_firstChild && !newChild->isTableCell())
            needsTable = false;
    }

    if (needsTable) {
        RenderTable* table;
        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : m_lastChild;
        if (afterChild && afterChild->isAnonymous() && afterChild->isTable())
            table = static_cast<RenderTable*>(afterChild);
        else {
            table = new (renderArena()) RenderTable(document() /* is anonymous */);
            RefPtr<RenderStyle> newStyle = RenderStyle::create();
            newStyle->inheritFrom(style());
            newStyle->setDisplay(TABLE);
            table->setStyle(newStyle.release());
            addChild(table, beforeChild);
        }
        table->addChild(newChild);
    } else {
        // just add it...
        insertChildNode(newChild, beforeChild);
    }

    if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE) {
        RefPtr<StringImpl> textToTransform = static_cast<RenderText*>(newChild)->originalText();
        if (textToTransform)
            static_cast<RenderText*>(newChild)->setText(textToTransform.release(), true);
    }
}
void CameraComponent::CreateComponent(luabridge::LuaRef& tableInfo, std::string name)
{
	auto cameraOffset = tableInfo["cameraOffset"];
	if (cameraOffset.isTable())
	{
		if (cameraOffset.length() == 3)
		{
			// LuaRef starts indexes from 1, not 0
			this->m_v3CamOffset = Vector3(cameraOffset.rawget<float>(1), cameraOffset.rawget<float>(2), cameraOffset.rawget<float>(3));
		}
		else
		{
			std::cout << "CameraComponent.cameraOffset for " + name + " is not an array with 3 values!" << std::endl;
		}
	}
	else
	{
		std::cout << "CameraComponent.cameraOffset for " + name + " is not an array with 3 values!" << std::endl;
	}

	auto cameraMode = tableInfo["cameraMode"];
	if (cameraMode.isNumber())
	{
		this->m_Camera->setCameraMode(Camera::CAMERA_MODE(cameraMode.cast<int>()));
	}
	else
	{
		std::cout << "CameraComponent.cameraMode for " + name + " is not a valid mode!" << std::endl;
	}
}
示例#3
0
    bool Environment::init() {
        getGlobal("_E");

        if (!isTable(-1)) {
            newTable(regFunctions->length());
            lua_setglobal(L, "_E");
        }
        pop(1);


        loopv(*regFunctions) {
            (*regFunctions)[i]();

        }

        delete regFunctions;

    luvit_init(L, uv_default_loop());
#ifdef SERVER

      /* Pull up the preload table */
    select("package", "preload");

    pushRow("native_server", server::lua::luaopen_server);

    pop(2);
#endif
#ifdef LUA_PANIC_DEBUG
    #pragma message("Using lua atpanic crasher.")
    lua_atpanic(L, crash);
#endif
        isInitialized = true;

        return true;
    }
示例#4
0
TEST_F (NamespaceTests, Variables)
{
  int int_ = -10;
  auto any = luabridge::newTable (L);
  any ["a"] = 1;

  ASSERT_THROW (
    luabridge::getGlobalNamespace (L).addProperty ("int", &int_),
    std::logic_error);

  runLua ("result = int");
  ASSERT_TRUE (result ().isNil ());

  luabridge::getGlobalNamespace (L)
    .beginNamespace ("ns")
    .addProperty ("int", &int_)
    .addProperty ("any", &any)
    .endNamespace ();

  ASSERT_EQ (-10, variable <int> ("ns.int"));
  ASSERT_EQ (any, variable <luabridge::LuaRef> ("ns.any"));

  runLua ("ns.int = -20");
  ASSERT_EQ (-20, int_);

  runLua ("ns.any = {b = 2}");
  ASSERT_TRUE (any.isTable ());
  ASSERT_TRUE (any ["b"].isNumber ());
  ASSERT_EQ (2, any ["b"].cast <int> ());
}
示例#5
0
Table&
Value::toTable()
{
    if (not isTable()) {
        throw utils::CastError(_("Value is not a table"));
    }
    return static_cast<Table&>(*this);
}
示例#6
0
void LuaInterface::setGlobalEnvironment(int env)
{
    pushThread();
    getRef(env);
    assert(isTable());
    setEnv();
    pop();
}
示例#7
0
void LuaInterface::getGlobalField(const std::string& globalKey, const std::string& fieldKey)
{
    getGlobal(globalKey);
    if(!isNil()) {
        assert(isTable() || isUserdata());
        getField(fieldKey);
        remove(-2);
    }
}
示例#8
0
std::vector<DatabaseColumn *> SociContainer::loadColumns(void)
{
	// When we have an empty table, the query doesn't return any rows and we
	// can't determine the columns from it. So if we have a tablename, we can
	// use this to geet the columns in a database specific way.
	// If this happens with a query, it possibly will fail and return empty.
	if(isTable())
		return readColumnsFromTable(getTablename());

	return readColumnsFromQuery(selectorToQuery(), true);
}
    forEach(moveit_msgs::CollisionObject & co, objectRecognitionNewObjects) {

        if(!add_objects_){
          if(!isTable(co.type)){
            ROS_INFO("Object was not added because adding objects was disabled: %s", co.id.c_str());
            break;
          }
        }
        co.operation = moveit_msgs::CollisionObject::ADD;
        planning_scene.world.collision_objects.push_back(co);
        ROS_INFO("Adding new object: %s", co.id.c_str());
    }
示例#10
0
static void
find_basetables( sql_rel *rel, list *tables )
{
	if (!rel)
		return;
	switch (rel->op) {
	case op_basetable: {
		sql_table *t = rel->l;

		if (t && isTable(t)) 
			append(tables, rel);
		break;
	}
	case op_table:
		break;
	case op_join: 
	case op_left: 
	case op_right: 
	case op_full: 

	case op_semi: 
	case op_anti: 
	case op_apply: 

	case op_union: 
	case op_inter: 
	case op_except: 
		if (rel->l)
			find_basetables(rel->l, tables); 
		if (rel->r)
			find_basetables(rel->r, tables); 
		break;
	case op_groupby: 
	case op_project:
	case op_select: 
	case op_topn: 
	case op_sample: 
		if (rel->l)
			find_basetables(rel->l, tables); 
		break;
	case op_ddl: 
		break;
	case op_insert:
	case op_update:
	case op_delete:
	case op_truncate:
		if (rel->r)
			find_basetables(rel->r, tables); 
		break;
	}
}
 // set colors
 // for some reason a diff replaces colors, so re-set the colors for known objects somewhere else
 // Do these now before we remove the unexpected ones
 // The extra colors for then-removed objects shouldnt hurt
 forEach(const moveit_msgs::CollisionObject & co, planningSceneUndetectedObjects) {
     moveit_msgs::ObjectColor oc;
     oc.id = co.id;
     if(isTable(co.type)) {
         oc.color.r = 0.67;
         oc.color.g = 0.33;
         oc.color.b = 0.0;
         oc.color.a = 1.0;
     } else {
         oc.color.r = 0.0;
         oc.color.g = 1.0;
         oc.color.b = 0.0;
         oc.color.a = 1.0;
     }
     planning_scene.object_colors.push_back(oc);
 }
示例#12
0
static void WriteMapVariablesXML(ironfist_map::map_t& m) {

	std::map<std::string, mapVariable> mapVariables = LoadMapVariablesFromLUA();

	for (std::map<std::string, mapVariable>::const_iterator it = mapVariables.begin(); it != mapVariables.end(); ++it) {
		ironfist_map::mapVariable_t mapVar;
		mapVar.id(it->first);
		mapVar.type(MapVarTypeToString(it->second.type));
		if (isTable(it->second.type)) {
			mapVar.table(WriteMapVariableTableXML(it->first, it->second.tableValue));
		} else if (isStringNumBool(it->second.type)) {
			mapVar.value(*it->second.singleValue);
		} else {
			DisplayError("Wrong Type created by GetMapVariables", "In function SaveMapVariables");
		}
		m.mapVariable().push_back(mapVar);
	}
}
示例#13
0
void LuaInterface::clearTable(int index)
{
    assert(hasIndex(index) && isTable(index));
    pushNil(); // table, nil
    bool stop = false;
    while(next(index-1)) { // table, key, value
        pop(); // table, key
        pushValue(); // table, key, key
        if(next(index-2)) { // table, key, nextkey, value
            pop(); // table, key, nextkey
            insert(-2); // table, nextkey, key
            pushNil(); // table, nextkey, key, nil
            rawSet(index-3); // table, nextkey
        } else { // table, key
            pushNil(); // table, key, nil
            rawSet(index-2); // table
            break;
        }
    }
}
示例#14
0
static lng
rel_getcount(mvc *sql, sql_rel *rel)
{
	if (!sql->session->tr)
		return 0;

	switch(rel->op) {
	case op_basetable: {
		sql_table *t = rel->l;

		if (t && isTable(t))
			return (lng)store_funcs.count_col(sql->session->tr, t->columns.set->h->data, 1);
		if (!t && rel->r) /* dict */
			return (lng)sql_trans_dist_count(sql->session->tr, rel->r);
		return 0;
	}
	default:
		assert(0);
		return 0;
	}
}
示例#15
0
bool SQLite::dumpTable(String* dest,LPCSTR tableName)
{
	if(!m_sqlite || !isTable(tableName))
		return false;

	String s;
	String sql;

	sql.printf("select sql from sqlite_master where name=\"%s\";",SQLSTRING(tableName));
	SQRes res = exec(sql);
	dest->appendf("%s;\n",res->getColumn(0));


	sql.printf("select * from %s;",SQLSTRING(tableName));
	SQRes data = exec(sql);


	INT c,r;
	INT cols = data->getFeilds();
	INT rows = data->getRows();
	
	for(r=0;r<rows;r++)
	{
		String work;
		for(c=0;c<cols;c++)
		{
			if(c)
				work += ',';
			work.appendf("'%s'",SQLSTRING(data->getColumn(r,c)));
		}
		s.appendf("INSERT INTO %s values(%s);\n",SQLSTRING(tableName),work.c_str());
	}
	*dest += s;

	return true;
}
示例#16
0
void game::LoadGame(char* filnam, int newGame, int a3) {
	if(newGame) {
		this->SetupOrigData();

		gpGame->ResetIronfistGameState();

		for(int i = 0; i < MAX_HEROES; i++) {
			//SetupOrigData clears out spellsLearned. Of course, we've changed
			//spellsLearned from an array to a pointer, so that actually NULLs it out
			this->heroes[i].ResetSpellsLearned();
		}
	} else {
		try {
			int fd;
			
			char v8[100];
			int v14 = 0;
			gbGameOver = 0;
			this->field_660E = 1;
			sprintf(v8, "%s%s", ".\\GAMES\\", filnam);

			/*
			 * Check if original save format
			 */
			fd = _open(v8, O_BINARY);
			char first_byte;
			_read(fd, &first_byte, sizeof(first_byte));
			_close(fd);

			if(first_byte != '<') {
				this->LoadGame_orig(filnam, newGame, a3);
				return;
			}

			std::auto_ptr<ironfist_map::map_t> mp = ironfist_map::map(std::string(v8));

			int i = 0;
			for (ironfist_map::map_t::hero_const_iterator it = mp->hero().begin();
			it != mp->hero().end();
				it++, i++) {
				ironfist_map::hero_t hx = *it;
				ReadHeroXML(hx, &this->heroes[i]);
			}

			int tmp_fd = _open(tmpFileName, O_BINARY | O_CREAT | O_WRONLY);
			_write(tmp_fd, mp->raw().data(), mp->raw().size());
			_close(tmp_fd);

			char expansion;
			char curPlayer;
			char hasPlayer[6];

			int width,height;

			fd = open(tmpFileName, O_BINARY | O_RDONLY);
			if ( fd == -1 )
				FileError(v8);
			ClearMapExtra();
			expansion = 1;

			_read(fd, &width, 4u);
			_read(fd, &height, 4u);
			this->SetMapSize(width, height);
			_read(fd, &this->mapHeader, sizeof(SMapHeader));
			_read(fd, &this->field_44D, 0x41u);
			_read(fd, this, 2u);
			_read(fd, &giMonthType, 1);
			_read(fd, &giMonthTypeExtra, 1u);
			_read(fd, &giWeekType, 1u);
			_read(fd, &giWeekTypeExtra, 1u);
			_read(fd, cPlayerNames, sizeof(cPlayerNames));

			gpAdvManager->PurgeMapChangeQueue();
			_read(fd, &giMapChangeCtr, 4u);

			sprintf(gpGame->lastSaveFile, filnam);
			_read(fd, &this->numPlayers, sizeof(this->numPlayers));
			_read(fd, &curPlayer, sizeof(curPlayer));
			giCurPlayer = curPlayer;
			_read(fd, &this->couldBeNumDefeatedPlayers, 1u);
			_read(fd, this->playerDead, 6u);

			_read(fd, hasPlayer, sizeof(hasPlayer));
			for(int i = 0; i < 6; ++i) {
				if(hasPlayer[i] && v14 < iLastMsgNumHumanPlayers) {
					++v14;
					gbHumanPlayer[i] = 1;
				} else {
					gbHumanPlayer[i] = 0;
				}
			}
			for(int i = 0; i < 6; ++i) {
				if(gbHumanPlayer[i])
					gbThisNetHumanPlayer[i] = !gbRemoteOn || i == giThisGamePos;
				else
					gbThisNetHumanPlayer[i] = 0;
			}

			_read(fd, &this->day, 2u);
			_read(fd, &this->week, 2u);
			_read(fd, &this->month, 2u);
			giCurTurn = this->day + 7 * (this->week - 1) + 28 * (this->month - 1);
			for(int i = 0; i < 6; ++i)
				this->players[i].Read(fd);
			_read(fd, &this->numObelisks, 1u);
			_read(fd, this->relatedToHeroForHireStatus, 0x36u);
			_read(fd, this->castles, 7200u);
			_read(fd, this->field_2773, 0x48u);
			_read(fd, this->field_27BB, 9u);
			_read(fd, this->mines, 0x3F0u);
			_read(fd, this->field_60A6, 144u);

			_read(fd, this->artifactGeneratedRandomly, 0x67u);
			_read(fd, this->boats, 0x180u);
			_read(fd, this->boatBuilt, 0x30u);
			_read(fd, this->obeliskVisitedMasks, 0x30u);
			_read(fd, &this->field_6395, 1u);
			_read(fd, &this->field_6396, 1u);
			_read(fd, &this->field_6397, 1u);
			_read(fd, this->currentRumor, 301u);
			_read(fd, this->field_637D, 0x18u);
			_read(fd, &this->numRumors, 4u);
			_read(fd, this->rumorIndices, 2 * this->numRumors);
			_read(fd, &this->numEvents, 4u);
			_read(fd, this->eventIndices, 2 * this->numEvents);
			_read(fd, &this->field_657B, 4u);
			_read(fd, this->_D, 2 * this->field_657B);
			_read(fd, &iMaxMapExtra, 4u);
			ppMapExtra = (void**)ALLOC(4 * iMaxMapExtra);
			pwSizeOfMapExtra = (short*)ALLOC(2 * iMaxMapExtra);
			memset(ppMapExtra, 0, 4 * iMaxMapExtra);
			memset(pwSizeOfMapExtra, 0, 2 * iMaxMapExtra);
			for(int i = 1; i < iMaxMapExtra; ++i ) {
				_read(fd, &pwSizeOfMapExtra[i], 2u);
				ppMapExtra[i] = ALLOC(pwSizeOfMapExtra[i]);
				_read(fd, ppMapExtra[i], pwSizeOfMapExtra[i]);
			}
			_read(fd, mapRevealed, MAP_HEIGHT * MAP_WIDTH);
			this->map.Read(fd, 0);
			SetFileAttributes(tmpFileNameW, GetFileAttributes(tmpFileNameW) & ~FILE_ATTRIBUTE_READONLY);
			_close(fd);
			remove(tmpFileName);
            gpAdvManager->heroMobilized = 0;
			gpCurPlayer = &gpGame->players[giCurPlayer];
			giCurPlayerBit = 1 << giCurPlayer;
			for(giCurWatchPlayer = giCurPlayer;
				!gbThisNetHumanPlayer[giCurWatchPlayer];
				giCurWatchPlayer = (giCurWatchPlayer + 1) % this->numPlayers )
				;
			giCurWatchPlayerBit = 1 << giCurWatchPlayer;
			bShowIt = gbThisNetHumanPlayer[giCurPlayer];
			this->SetupAdjacentMons();
			gpAdvManager->CheckSetEvilInterface(0, -1);

            gpGame->ResetIronfistGameState();

			if (mp->script().present()) {
				ScriptingInitFromString(mp->script().get());
			}

			std::map<std::string, mapVariable> mapVariables;
			for (ironfist_map::map_t::mapVariable_const_iterator it = mp->mapVariable().begin();
				it != mp->mapVariable().end(); it++) {
				mapVariable *mapVar = new mapVariable;
				std::string mapVariableId = it->id().get();
				MapVarType mapVariableType = StringToMapVarType(it->type());
				mapVar->type = mapVariableType;
				if (isTable(mapVariableType)) {
					mapVar->tableValue = ReadMapVarXML(it->table().get());
				} else if (isStringNumBool(mapVariableType)) {
					std::string *sV = new std::string;
					*sV = it->value().get();
					mapVar->singleValue = sV;
				} else {
					ErrorLoadingMapVariable(mapVariableId, " A map variable can only be a table, number, string or boolean.");
				}
				mapVariables[mapVariableId] = *mapVar;
			}
			WriteMapVariablesToLUA(mapVariables);

		} catch(xml_schema::exception& e) {
            DisplayError("Error parsing save file", "Fatal Error");
			std::cerr << e << std::endl;
			exit(1);
		}
	}
}
示例#17
0
int LuaInterface::signalCall(int numArgs, int numRets)
{
    int rets = 0;
    int funcIndex = -numArgs-1;

    try {
        // must be a function
        if(isFunction(funcIndex)) {
            rets = safeCall(numArgs);

            if(numRets != -1) {
                if(rets != numRets)
                    throw LuaException("function call didn't return the expected number of results", 0);
            }
        }
        // can also calls table of functions
        else if(isTable(funcIndex)) {
            // loop through table values
            pushNil();
            bool done = false;
            while(next(funcIndex-1)) {
                if(isFunction()) {
                    // repush arguments
                    for(int i=0;i<numArgs;++i)
                        pushValue(-numArgs-2);

                    int rets = safeCall(numArgs);
                    if(rets == 1) {
                        done = popBoolean();
                        if(done) {
                            pop();
                            break;
                        }
                    } else if(rets != 0)
                        throw LuaException("function call didn't return the expected number of results", 0);
                } else {
                    throw LuaException("attempt to call a non function", 0);
                }
            }
            pop(numArgs + 1); // pops the table of function and arguments

            if(numRets == 1 || numRets == -1) {
                rets = 1;
                pushBoolean(done);
            }
        }
        // nil values are ignored
        else if(isNil(funcIndex)) {
            pop(numArgs + 1); // pops the function and arguments
        }
        // if not nil, warn
        else {
            throw LuaException("attempt to call a non function value", 0);
        }
    } catch(stdext::exception& e) {
        g_logger.error(stdext::format("protected lua call failed: %s", e.what()));
    }

    // pushes nil values if needed
    while(numRets != -1 && rets < numRets) {
        pushNil();
        rets++;
    }

    // returns the number of results on the stack
    return rets;
}
示例#18
0
void LuaInterface::setField(const char* key, int index)
{
    assert(hasIndex(index));
    assert(isUserdata(index) || isTable(index));
    lua_setfield(L, index, key);
}
示例#19
0
int NpcScriptInterface::luaNpcOpenShopWindow(lua_State* L)
{
    // npc:openShopWindow(cid, items, buyCallback, sellCallback)
    if (!isTable(L, 3)) {
        reportErrorFunc("item list is not a table.");
        pushBoolean(L, false);
        return 1;
    }

    Player* player = getPlayer(L, 2);
    if (!player) {
        reportErrorFunc(getErrorDesc(LUA_ERROR_PLAYER_NOT_FOUND));
        pushBoolean(L, false);
        return 1;
    }

    Npc* npc = getUserdata<Npc>(L, 1);
    if (!npc) {
        reportErrorFunc(getErrorDesc(LUA_ERROR_CREATURE_NOT_FOUND));
        pushBoolean(L, false);
        return 1;
    }

    int32_t sellCallback = -1;
    if (LuaScriptInterface::isFunction(L, 5)) {
        sellCallback = luaL_ref(L, LUA_REGISTRYINDEX);
    }

    int32_t buyCallback = -1;
    if (LuaScriptInterface::isFunction(L, 4)) {
        buyCallback = luaL_ref(L, LUA_REGISTRYINDEX);
    }

    std::list<ShopInfo> items;

    lua_pushnil(L);
    while (lua_next(L, 3) != 0) {
        const auto tableIndex = lua_gettop(L);
        ShopInfo item;

        item.itemId = getField<uint32_t>(L, tableIndex, "id");
        item.subType = getField<int32_t>(L, tableIndex, "subType");
        if (item.subType == 0) {
            item.subType = getField<int32_t>(L, tableIndex, "subtype");
            lua_pop(L, 1);
        }

        item.buyPrice = getField<uint32_t>(L, tableIndex, "buy");
        item.sellPrice = getField<uint32_t>(L, tableIndex, "sell");
        item.realName = getFieldString(L, tableIndex, "name");

        items.push_back(item);
        lua_pop(L, 6);
    }
    lua_pop(L, 1);

    player->closeShopWindow(false);
    npc->addShopPlayer(player);

    player->setShopOwner(npc, buyCallback, sellCallback);
    player->openShopWindow(npc, items);

    pushBoolean(L, true);
    return 1;
}
示例#20
0
VisiblePosition RenderContainer::positionForCoordinates(int x, int y)
{
    // no children...return this render object's element, if there is one, and offset 0
    if (!m_firstChild)
        return VisiblePosition(element(), 0, DOWNSTREAM);

    if (isTable() && element()) {
        int right = contentWidth() + borderRight() + paddingRight() + borderLeft() + paddingLeft();
        int bottom = contentHeight() + borderTop() + paddingTop() + borderBottom() + paddingBottom();

        if (x < 0 || x > right || y < 0 || y > bottom) {
            if (x <= right / 2)
                return VisiblePosition(Position(element(), 0));
            else
                return VisiblePosition(Position(element(), maxDeepOffset(element())));
        }
    }

    // Pass off to the closest child.
    int minDist = INT_MAX;
    RenderObject* closestRenderer = 0;
    int newX = x;
    int newY = y;
    if (isTableRow()) {
        newX += xPos();
        newY += yPos();
    }
    for (RenderObject* renderer = m_firstChild; renderer; renderer = renderer->nextSibling()) {
        if (!renderer->firstChild() && !renderer->isInline() && !renderer->isBlockFlow()
                || renderer->style()->visibility() != VISIBLE)
            continue;

        int top = borderTop() + paddingTop() + (isTableRow() ? 0 : renderer->yPos());
        int bottom = top + renderer->contentHeight();
        int left = borderLeft() + paddingLeft() + (isTableRow() ? 0 : renderer->xPos());
        int right = left + renderer->contentWidth();

        if (x <= right && x >= left && y <= top && y >= bottom) {
            if (renderer->isTableRow())
                return renderer->positionForCoordinates(x + newX - renderer->xPos(), y + newY - renderer->yPos());
            return renderer->positionForCoordinates(x - renderer->xPos(), y - renderer->yPos());
        }

        // Find the distance from (x, y) to the box.  Split the space around the box into 8 pieces
        // and use a different compare depending on which piece (x, y) is in.
        IntPoint cmp;
        if (x > right) {
            if (y < top)
                cmp = IntPoint(right, top);
            else if (y > bottom)
                cmp = IntPoint(right, bottom);
            else
                cmp = IntPoint(right, y);
        } else if (x < left) {
            if (y < top)
                cmp = IntPoint(left, top);
            else if (y > bottom)
                cmp = IntPoint(left, bottom);
            else
                cmp = IntPoint(left, y);
        } else {
            if (y < top)
                cmp = IntPoint(x, top);
            else
                cmp = IntPoint(x, bottom);
        }

        int x1minusx2 = cmp.x() - x;
        int y1minusy2 = cmp.y() - y;

        int dist = x1minusx2 * x1minusx2 + y1minusy2 * y1minusy2;
        if (dist < minDist) {
            closestRenderer = renderer;
            minDist = dist;
        }
    }

    if (closestRenderer)
        return closestRenderer->positionForCoordinates(newX - closestRenderer->xPos(), newY - closestRenderer->yPos());

    return VisiblePosition(element(), 0, DOWNSTREAM);
}