<commit_before>
/*
 *  SubtitleStream.cpp
 *  sfeMovie project
 *
 *  Copyright (C) 2010-2014 Stephan Vedder
 *  stephan.vedder@gmail.com
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

extern "C"
{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}

#include <sfeMovie/Movie.hpp>
#include "SubtitleStream.hpp"
#include "Log.hpp"

#include <iostream>
#include <cassert>
#include <stdint.h>

namespace sfe
{
    const int RGBASize = 4;

    SubtitleStream::SubtitleStream(AVFormatContext*& formatCtx, AVStream*& stream, DataSource& dataSource, std::shared_ptr<Timer> timer, Delegate& delegate) :
        Stream(formatCtx, stream, dataSource, timer), m_delegate(delegate), m_library(nullptr), m_renderer(nullptr), m_track(nullptr)
    {
        const AVCodecDescriptor* desc = av_codec_get_codec_descriptor(m_stream->codec);
        CHECK(desc != NULL, "Could not get the codec descriptor!");

        if((desc->props & AV_CODEC_PROP_BITMAP_SUB)==0)
        {
			m_library  = ass_library_init();
            ass_set_message_cb(m_library, ass_log,nullptr);

			m_renderer = ass_renderer_init(m_library);
            m_track    = ass_new_track(m_library);

		}
    }

    /** Default destructor
     */
    SubtitleStream::~SubtitleStream()
    {
        if (m_track)
        {
            ass_free_track(m_track);
            m_track = nullptr;
        }

		if(m_renderer)
		{
			ass_renderer_done(m_renderer);
			m_renderer = nullptr;
		}

		if(m_library)
		{
			ass_library_done(m_library);
			m_library = nullptr;
		}

    }

    MediaType SubtitleStream::getStreamKind() const
    {
        return Subtitle;
    }

    void SubtitleStream::update()
    {
        //only get new subtitles if we are running low
        if (m_status == Playing && hasPackets())
        {
            if (!onGetData())
                setStatus(Stopped);
        }

        if (m_pendingSubtitles.size() > 0)
        {
            //activate subtitle
            if (m_pendingSubtitles.front()->start < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> iter = m_pendingSubtitles.front();

                m_delegate.didUpdateSubtitle(*this, iter->sprites, iter->positions);
                m_visibleSubtitles.push_back(iter);
                m_pendingSubtitles.pop_front();
            }
        }

        if (m_visibleSubtitles.size()>0)
        {
            //remove subtitle
            if (m_visibleSubtitles.front()->end < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> subtitle = m_visibleSubtitles.front();
                m_visibleSubtitles.pop_front();

                if (m_visibleSubtitles.size() == 0)
                {
                    m_delegate.didWipeOutSubtitles(*this);
                }
            }
        }
    }

    bool SubtitleStream::isPassive() const
    {
        return true;
    }

    bool SubtitleStream::onGetData()
    {
        AVPacket* packet = popEncodedData();
        AVSubtitle sub;
        int32_t gotSub = 0;
        int32_t goOn = 0;
        int64_t pts = 0;

        if (packet)
        {
            goOn = 1;

            while (!gotSub && packet && goOn)
            {
                bool needsMoreDecoding = false;

                CHECK(packet != nullptr, "inconsistency error");
                goOn = avcodec_decode_subtitle2(m_stream->codec, &sub, &gotSub, packet);

                pts = 0;
                if (packet->pts != AV_NOPTS_VALUE)
                    pts = packet->pts;

                if (gotSub && pts)
                {
                    bool succeeded = false;
                    std::shared_ptr<SubtitleData> sfeSub = std::make_shared<SubtitleData>(&sub, succeeded);

                    if (succeeded)
                        m_pendingSubtitles.push_back(sfeSub);
                }

                if (needsMoreDecoding)
                {
                    prependEncodedData(packet);
                }
                else
                {
                    av_free_packet(packet);
                    av_free(packet);
                }

                if (!gotSub && goOn)
                {
                    sfeLogDebug("no subtitle in this packet, reading further");
                    packet = popEncodedData();
                }
            }
        }
        return (goOn >= 0);
    }

    SubtitleStream::SubtitleData::SubtitleData(AVSubtitle* sub, bool& succeeded,ASS_Track* track)
    {
        assert(sub != nullptr);

        succeeded = false;
        start = sf::milliseconds(sub->start_display_time) + sf::microseconds(sub->pts);
        end = sf::milliseconds(sub->end_display_time) + sf::microseconds(sub->pts);

        for (unsigned int i = 0; i < sub->num_rects; ++i)
        {

            sprites.push_back(sf::Sprite());
            textures.push_back(sf::Texture());

            sf::Sprite& sprite = sprites.back();
            sf::Texture& texture = textures.back();
            AVSubtitleRect* subItem = sub->rects[i];

            AVSubtitleType type = subItem->type;

            if (type == SUBTITLE_BITMAP)
            {
                CHECK(subItem->pict.data != nullptr, "FFmpeg inconcistency error");
                CHECK(subItem->w * subItem->h > 0, "FFmpeg inconcistency error");

                positions.push_back(sf::Vector2i(subItem->x, subItem->y));

                std::unique_ptr<uint32_t[]> palette(new uint32_t[subItem->nb_colors]);
                for (int j = 0; j < subItem->nb_colors; j++)
                    palette[j] = *(uint32_t*)&subItem->pict.data[1][j * RGBASize];

                texture.create(subItem->w, subItem->h);
                texture.setSmooth(true);

                std::unique_ptr<uint32_t[]> data(new uint32_t[subItem->w* sub->rects[i]->h]);
                for (int j = 0; j < subItem->w * subItem->h; ++j)
                    data[j] = palette[subItem->pict.data[0][j]];

                texture.update((uint8_t*)data.get());
                sprite.setTexture(texture);

                succeeded = true;
            }
            else
            {
                ass_process_data(track, subItem->ass, strlen(subItem->ass));
            }
        }
    }

    void SubtitleStream::flushBuffers()
    {
        m_delegate.didWipeOutSubtitles(*this);
        Stream::flushBuffers();
    }

    void SubtitleStream::ass_log(int ass_level, const char *fmt, va_list args, void *data)
    {
        char buffer[100];
        sprintf(buffer, fmt, args);
        sfeLogDebug(buffer);
    }
}
<commit_msg>Did add initial render code and fixed a bug in ass_log<commit_after>
/*
 *  SubtitleStream.cpp
 *  sfeMovie project
 *
 *  Copyright (C) 2010-2014 Stephan Vedder
 *  stephan.vedder@gmail.com
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License as published by the Free Software Foundation; either
 *  version 2.1 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
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 *
 */

extern "C"
{
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
}

#include <sfeMovie/Movie.hpp>
#include "SubtitleStream.hpp"
#include "Log.hpp"

#include <iostream>
#include <cassert>
#include <stdint.h>

namespace sfe
{
    const int RGBASize = 4;

    SubtitleStream::SubtitleStream(AVFormatContext*& formatCtx, AVStream*& stream, DataSource& dataSource, std::shared_ptr<Timer> timer, Delegate& delegate) :
        Stream(formatCtx, stream, dataSource, timer), m_delegate(delegate), m_library(nullptr), m_renderer(nullptr), m_track(nullptr)
    {
        const AVCodecDescriptor* desc = av_codec_get_codec_descriptor(m_stream->codec);
        CHECK(desc != NULL, "Could not get the codec descriptor!");

        if((desc->props & AV_CODEC_PROP_BITMAP_SUB)==0)
        {
			m_library  = ass_library_init();
            ass_set_message_cb(m_library, ass_log,nullptr);

			m_renderer = ass_renderer_init(m_library);
            m_track    = ass_new_track(m_library);

		}
    }

    /** Default destructor
     */
    SubtitleStream::~SubtitleStream()
    {
        if (m_track)
        {
            ass_free_track(m_track);
            m_track = nullptr;
        }

		if(m_renderer)
		{
			ass_renderer_done(m_renderer);
			m_renderer = nullptr;
		}

		if(m_library)
		{
			ass_library_done(m_library);
			m_library = nullptr;
		}

    }

    MediaType SubtitleStream::getStreamKind() const
    {
        return Subtitle;
    }

    void SubtitleStream::update()
    {
        //only get new subtitles if we are running low
        if (m_status == Playing && hasPackets())
        {
            if (!onGetData())
                setStatus(Stopped);
        }

        if (m_pendingSubtitles.size() > 0)
        {
            //activate subtitle
            if (m_pendingSubtitles.front()->start < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> iter = m_pendingSubtitles.front();

                //this is the case for ass subtitles
                if (iter->sprites.size() < 1)
                {
                    int change = 0;
                    ASS_Image* img = ass_render_frame(m_renderer, m_track, m_timer->getOffset().asMilliseconds(), &change);
                    if (change)
                    {
                        while (img)
                        {
                            iter->sprites.push_back(sf::Sprite());
                            iter->textures.push_back(sf::Texture());
                            iter->positions.push_back(sf::Vector2i(img->dst_x, img->dst_y));

                            sf::Sprite& sprite = iter->sprites.back();
                            sf::Texture& texture = iter->textures.back();

                            texture.create(img->w, img->h);
                            texture.update(img->bitmap);
                            texture.setSmooth(true);

                            sprite.setTexture(texture);

                            img = img->next;
                        }
                    }
                }

                m_delegate.didUpdateSubtitle(*this, iter->sprites, iter->positions);
                m_visibleSubtitles.push_back(iter);
                m_pendingSubtitles.pop_front();
            }
        }

        if (m_visibleSubtitles.size()>0)
        {
            //remove subtitle
            if (m_visibleSubtitles.front()->end < m_timer->getOffset())
            {
                std::shared_ptr<SubtitleData> subtitle = m_visibleSubtitles.front();
                m_visibleSubtitles.pop_front();

                if (m_visibleSubtitles.size() == 0)
                {
                    m_delegate.didWipeOutSubtitles(*this);
                }
            }
        }
    }

    bool SubtitleStream::isPassive() const
    {
        return true;
    }

    bool SubtitleStream::onGetData()
    {
        AVPacket* packet = popEncodedData();
        AVSubtitle sub;
        int32_t gotSub = 0;
        int32_t goOn = 0;
        int64_t pts = 0;

        if (packet)
        {
            goOn = 1;

            while (!gotSub && packet && goOn)
            {
                bool needsMoreDecoding = false;

                CHECK(packet != nullptr, "inconsistency error");
                goOn = avcodec_decode_subtitle2(m_stream->codec, &sub, &gotSub, packet);

                pts = 0;
                if (packet->pts != AV_NOPTS_VALUE)
                    pts = packet->pts;

                if (gotSub && pts)
                {
                    bool succeeded = false;
                    std::shared_ptr<SubtitleData> sfeSub = std::make_shared<SubtitleData>(&sub, succeeded,m_track);

                    if (succeeded)
                        m_pendingSubtitles.push_back(sfeSub);
                }

                if (needsMoreDecoding)
                {
                    prependEncodedData(packet);
                }
                else
                {
                    av_free_packet(packet);
                    av_free(packet);
                }

                if (!gotSub && goOn)
                {
                    sfeLogDebug("no subtitle in this packet, reading further");
                    packet = popEncodedData();
                }
            }
        }
        return (goOn >= 0);
    }

    SubtitleStream::SubtitleData::SubtitleData(AVSubtitle* sub, bool& succeeded,ASS_Track* track)
    {
        assert(sub != nullptr);

        succeeded = false;
        start = sf::milliseconds(sub->start_display_time) + sf::microseconds(sub->pts);
        end = sf::milliseconds(sub->end_display_time) + sf::microseconds(sub->pts);

        for (unsigned int i = 0; i < sub->num_rects; ++i)
        {
            AVSubtitleRect* subItem = sub->rects[i];

            AVSubtitleType type = subItem->type;

            if (type == SUBTITLE_BITMAP)
            {
                sprites.push_back(sf::Sprite());
                textures.push_back(sf::Texture());

                sf::Sprite& sprite = sprites.back();
                sf::Texture& texture = textures.back();

                CHECK(subItem->pict.data != nullptr, "FFmpeg inconcistency error");
                CHECK(subItem->w * subItem->h > 0, "FFmpeg inconcistency error");

                positions.push_back(sf::Vector2i(subItem->x, subItem->y));

                std::unique_ptr<uint32_t[]> palette(new uint32_t[subItem->nb_colors]);
                for (int j = 0; j < subItem->nb_colors; j++)
                    palette[j] = *(uint32_t*)&subItem->pict.data[1][j * RGBASize];

                texture.create(subItem->w, subItem->h);
                texture.setSmooth(true);

                std::unique_ptr<uint32_t[]> data(new uint32_t[subItem->w* sub->rects[i]->h]);
                for (int j = 0; j < subItem->w * subItem->h; ++j)
                    data[j] = palette[subItem->pict.data[0][j]];

                texture.update((uint8_t*)data.get());
                sprite.setTexture(texture);

                succeeded = true;
            }
            else
            {
                ass_process_data(track, subItem->ass, strlen(subItem->ass));

                succeeded = true;
            }
        }
    }

    void SubtitleStream::flushBuffers()
    {
        m_delegate.didWipeOutSubtitles(*this);
        Stream::flushBuffers();
    }

    void SubtitleStream::ass_log(int ass_level, const char *fmt, va_list args, void *data)
    {
        char buffer[100];

        vsprintf(buffer, fmt, args);
        sfeLogDebug(buffer);
    }
}
<|endoftext|>


<commit_before>#include <iostream>
#include <random>
#include <queue>
#include <SFML/System.hpp>

#include "Map.h"
#include "PoissonDiskSampling/PoissonDiskSampling.h"
#include "Math/Vector2.h"
#include "Noise/Noise.h"

const std::vector<std::vector<BiomeType>> Map::m_elevationMoistureMatrix = MakeBiomeMatrix();

std::vector<std::vector<BiomeType>> Map::MakeBiomeMatrix()
{
	std::vector<std::vector<BiomeType>> matrix;
	std::vector<BiomeType> biomeVector;

	biomeVector.push_back(BiomeType::SubtropicalDesert);
	biomeVector.push_back(BiomeType::TemprateDesert);
	biomeVector.push_back(BiomeType::TemprateDesert);
	biomeVector.push_back(BiomeType::Mountain);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	biomeVector.push_back(BiomeType::Grassland);
	biomeVector.push_back(BiomeType::Grassland);
	biomeVector.push_back(BiomeType::TemprateDesert);
	biomeVector.push_back(BiomeType::Mountain);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	biomeVector.push_back(BiomeType::TropicalSeasonalForest);
	biomeVector.push_back(BiomeType::Grassland);
	biomeVector.push_back(BiomeType::Shrubland);
	biomeVector.push_back(BiomeType::Tundra);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	biomeVector.push_back(BiomeType::TropicalSeasonalForest);
	biomeVector.push_back(BiomeType::TemprateDeciduousForest);
	biomeVector.push_back(BiomeType::Shrubland);
	biomeVector.push_back(BiomeType::Snow);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	biomeVector.push_back(BiomeType::TropicalRainForest);
	biomeVector.push_back(BiomeType::TemprateDeciduousForest);
	biomeVector.push_back(BiomeType::Taiga);
	biomeVector.push_back(BiomeType::Snow);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	biomeVector.push_back(BiomeType::TropicalRainForest);
	biomeVector.push_back(BiomeType::TemprateRainForest);
	biomeVector.push_back(BiomeType::Taiga);
	biomeVector.push_back(BiomeType::Snow);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	return matrix;
}

Map::Map(int width, int height, double pointSpread, std::string seed) :
	m_mapWidth(width), m_mapHeight(height), m_pointSpread(pointSpread), m_zCoord(0.0),
	m_noiseMap(nullptr), m_seed(seed), m_centersQuadTree(AABB(Vector2(width / 2, height / 2), Vector2(width / 2, height / 2)), 1)
{
	double approxPointCount = (2 * m_mapWidth * m_mapHeight) / (3.1416 * m_pointSpread * m_pointSpread);
	int maxTreeDepth = floor((log(approxPointCount) / log(4)) + 0.5);
	QuadTree<Center*>::SetMaxDepth(maxTreeDepth);

	m_seed = seed != "" ? seed : CreateSeed(20);
	std::mt19937 mt_rand(HashString(m_seed));

	m_zCoord = mt_rand();
	std::cout << "Seed: " << m_seed << "(" << HashString(m_seed) << ")" << std::endl;
}

void Map::Generate()
{
	sf::Clock timer;

	GeneratePolygons();

	std::cout << "Land distribution: ";
	timer.restart();
	GenerateLand();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	// Elevation
	std::cout << "Coast assignment: ";
	timer.restart();
	AssignOceanCoastLand();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Corner altitude: ";
	timer.restart();
	AssignCornerElevations();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Altitude redistribution: ";
	timer.restart();
	RedistributeElevations();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Center altitude: ";
	timer.restart();
	AssignPolygonElevations();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	// Moisture
	std::cout << "Downslopes: ";
	timer.restart();
	CalculateDownslopes();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "River generation: ";
	timer.restart();
	GenerateRivers();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Corner moisture: ";
	timer.restart();
	AssignCornerMoisture();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Moisture redistribution: ";
	timer.restart();
	RedistributeMoisture();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Center moisture: ";
	timer.restart();
	AssignPolygonMoisture();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	// Biomes
	std::cout << "Biome assignment: ";
	timer.restart();
	AssignBiomes();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Populate Quadtree: ";
	timer.restart();
	for (auto center : m_centers)
	{
		std::pair<Vector2, Vector2> aabb(center->GetBoundingBox());
		m_centersQuadTree.Insert2(center, AABB(aabb.first, aabb.second));
	}
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;
}

void Map::GeneratePolygons()
{
	sf::Clock timer;

	GeneratePoints();
	std::cout << "Point placement: " << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;
	timer.restart();

	Triangulate(m_points);
	std::cout << "Triangulation: " << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;
	timer.restart();

	FinishInfo();
	std::cout << "Finishing touches: " << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;
}

void Map::GenerateLand()
{
	m_noiseMap = new noise::module::Perlin();

	for (auto corner : m_corners)
	{
		if (!corner->IsInsideBoundingBox(m_mapWidth, m_mapHeight))
		{
			corner->m_border = true;
			corner->m_ocean = true;
			corner->m_water = true;
		}
	}

	for (auto corner : m_corners)
	{
		corner->m_water = !IsIsland(corner->m_position);
	}
}

std::vector<Edge*> Map::GetEdges() const
{
	return m_edges;
}

std::vector<Corner*> Map::GetCorners() const
{
	return m_corners;
}

std::vector<Center*> Map::GetCenters() const
{
	return m_centers;
}

Center* Map::GetCenterAt(Vector2 pos)
{
	Center* center = nullptr;
	std::vector<Center*> auxCenters = m_centersQuadTree.QueryRange(pos);

	if (auxCenters.size() > 0)
	{
		double minDist = Vector2(auxCenters[0]->m_position, pos).Length();
		center = auxCenters[0];

		for (auto auxCenter : auxCenters)
		{
			double newDist = Vector2(auxCenter->m_position, pos).Length();
			if (newDist < minDist)
			{
				minDist = newDist;
				center = auxCenter;
			}
		}
	}

	return center;
}

bool Map::IsIsland(Vector2 position)
{
	double waterThreshold = 0.075;

	if (position.x < m_mapWidth * waterThreshold || position.y < m_mapHeight * waterThreshold ||
		position.x > m_mapWidth * (1 - waterThreshold) || position.y > m_mapHeight * (1 - waterThreshold))
	{
		return false;
	}

	Vector2 centerPos = Vector2(m_mapWidth / 2.0, m_mapHeight / 2.0);
	position -= centerPos;

	double xCoord = (position.x / m_mapWidth) * 4;
	double yCoord = (position.y / m_mapHeight) * 4;
	double noiseVal = m_noiseMap->GetValue(xCoord, yCoord, m_zCoord);

	position /= std::min(m_mapWidth, m_mapHeight);
	double radius = position.Length();

	double factor = radius - 0.5;

	return noiseVal >= 0.3 * radius + factor;
}

void Map::CalculateDownslopes()
{
	for (auto c : m_corners)
	{
		Corner* d = c;
		for (auto q : c->m_corners)
		{
			if (q->m_elevation < d->m_elevation)
			{
				d = q;
			}
		}

		c->m_downslope = d;
	}
}

void Map::GenerateRivers()
{
	std::mt19937 mt_rand(HashString(m_seed));
	int numRivers = m_centers.size() / 3;

	for (int i = 0; i < numRivers; ++i)
	{
		Corner* q = m_corners[mt_rand() % m_corners.size()];

		if (q->m_ocean || q->m_elevation < 0.3 || q->m_elevation > 0.9)
		{
			continue;
		}

		while (!q->m_coast)
		{
			if (q == q->m_downslope)
			{
				break;
			}

			Edge* e = q->GetEdgeWith(q->m_downslope);
			e->m_riverVolume += 1;
			q->m_riverVolume += 1;
			q->m_downslope->m_riverVolume += 1;
			q = q->m_downslope;
		}
	}
}

void Map::AssignOceanCoastLand()
{
	std::queue<Center*> centersQueue;

	for (auto c : m_centers)
	{
		int adjacentWater = 0;

		for (auto q : c->m_centers)
		{
			if (q->m_border)
			{
				c->m_border = true;
				c->m_ocean = true;
				q->m_water = true;
				centersQueue.push(c);
			}

			if (q->m_water)
			{
				adjacentWater++;
			}
		}

		c->m_water = (c->m_ocean || adjacentWater >= c->m_corners.size() * 0.5);
	}

	while (!centersQueue.empty())
	{
		Center* c = centersQueue.front();
		centersQueue.pop();

		for (auto r : c->m_centers)
		{
			if (r->m_water && !r->m_ocean)
			{
				r->m_ocean = true;
				centersQueue.push(r);
			}
		}
	}

	for (auto p : m_centers)
	{
		int numOcean = 0;
		int numLand = 0;

		for (auto q : p->m_centers)
		{
			numOcean += static_cast<int>(q->m_ocean);
			numLand += static_cast<int>(!q->m_water);
		}

		p->m_coast = numLand > 0 && numOcean > 0;
	}

	for (auto c : m_corners)
	{
		int adjOcean = 0;
		int adjLand = 0;

		for (auto p : c->m_centers)
		{
			adjOcean += static_cast<int>(p->m_ocean);
			adjLand += static_cast<int>(!p->m_water);
		}

		c->m_ocean = adjOcean == c->m_centers.size();
		c->m_coast = adjLand > 0 && adjOcean > 0;
		c->m_water = c->m_border || (adjLand != c->m_centers.size() && !c->m_coast);
	}
}

void RedistributeElevations();
void AssignCornerElevations();
void AssignPolygonElevations();
void RedistributeMoisture();
void AssignCornerMoisture();
void AssignPolygonMoisture();
void AssignBiomes();

void GeneratePoints();
void Triangulate(std::vector<DelaunayTriangulation::Vertex> points);
void FinishInfo();
void AddCenter(Center* c);
Center* GetCenter(Vector2 position);
void OrderPoints(std::vector<Corner*>& corners);

std::vector<Corner*> GetLandCorners();
std::vector<Corner*> GetLakeCorners();
void LloydRelaxation();
std::string CreateSeed(int length);

static unsigned int HashString(std::string seed);<commit_msg>Implement Map::RedistributeElevations()<commit_after>#include <iostream>
#include <random>
#include <queue>
#include <SFML/System.hpp>

#include "Map.h"
#include "PoissonDiskSampling/PoissonDiskSampling.h"
#include "Math/Vector2.h"
#include "Noise/Noise.h"

const std::vector<std::vector<BiomeType>> Map::m_elevationMoistureMatrix = MakeBiomeMatrix();

std::vector<std::vector<BiomeType>> Map::MakeBiomeMatrix()
{
	std::vector<std::vector<BiomeType>> matrix;
	std::vector<BiomeType> biomeVector;

	biomeVector.push_back(BiomeType::SubtropicalDesert);
	biomeVector.push_back(BiomeType::TemprateDesert);
	biomeVector.push_back(BiomeType::TemprateDesert);
	biomeVector.push_back(BiomeType::Mountain);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	biomeVector.push_back(BiomeType::Grassland);
	biomeVector.push_back(BiomeType::Grassland);
	biomeVector.push_back(BiomeType::TemprateDesert);
	biomeVector.push_back(BiomeType::Mountain);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	biomeVector.push_back(BiomeType::TropicalSeasonalForest);
	biomeVector.push_back(BiomeType::Grassland);
	biomeVector.push_back(BiomeType::Shrubland);
	biomeVector.push_back(BiomeType::Tundra);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	biomeVector.push_back(BiomeType::TropicalSeasonalForest);
	biomeVector.push_back(BiomeType::TemprateDeciduousForest);
	biomeVector.push_back(BiomeType::Shrubland);
	biomeVector.push_back(BiomeType::Snow);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	biomeVector.push_back(BiomeType::TropicalRainForest);
	biomeVector.push_back(BiomeType::TemprateDeciduousForest);
	biomeVector.push_back(BiomeType::Taiga);
	biomeVector.push_back(BiomeType::Snow);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	biomeVector.push_back(BiomeType::TropicalRainForest);
	biomeVector.push_back(BiomeType::TemprateRainForest);
	biomeVector.push_back(BiomeType::Taiga);
	biomeVector.push_back(BiomeType::Snow);
	matrix.push_back(biomeVector);
	biomeVector.clear();

	return matrix;
}

Map::Map(int width, int height, double pointSpread, std::string seed) :
	m_mapWidth(width), m_mapHeight(height), m_pointSpread(pointSpread), m_zCoord(0.0),
	m_noiseMap(nullptr), m_seed(seed), m_centersQuadTree(AABB(Vector2(width / 2, height / 2), Vector2(width / 2, height / 2)), 1)
{
	double approxPointCount = (2 * m_mapWidth * m_mapHeight) / (3.1416 * m_pointSpread * m_pointSpread);
	int maxTreeDepth = floor((log(approxPointCount) / log(4)) + 0.5);
	QuadTree<Center*>::SetMaxDepth(maxTreeDepth);

	m_seed = seed != "" ? seed : CreateSeed(20);
	std::mt19937 mt_rand(HashString(m_seed));

	m_zCoord = mt_rand();
	std::cout << "Seed: " << m_seed << "(" << HashString(m_seed) << ")" << std::endl;
}

void Map::Generate()
{
	sf::Clock timer;

	GeneratePolygons();

	std::cout << "Land distribution: ";
	timer.restart();
	GenerateLand();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	// Elevation
	std::cout << "Coast assignment: ";
	timer.restart();
	AssignOceanCoastLand();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Corner altitude: ";
	timer.restart();
	AssignCornerElevations();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Altitude redistribution: ";
	timer.restart();
	RedistributeElevations();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Center altitude: ";
	timer.restart();
	AssignPolygonElevations();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	// Moisture
	std::cout << "Downslopes: ";
	timer.restart();
	CalculateDownslopes();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "River generation: ";
	timer.restart();
	GenerateRivers();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Corner moisture: ";
	timer.restart();
	AssignCornerMoisture();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Moisture redistribution: ";
	timer.restart();
	RedistributeMoisture();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Center moisture: ";
	timer.restart();
	AssignPolygonMoisture();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	// Biomes
	std::cout << "Biome assignment: ";
	timer.restart();
	AssignBiomes();
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;

	std::cout << "Populate Quadtree: ";
	timer.restart();
	for (auto center : m_centers)
	{
		std::pair<Vector2, Vector2> aabb(center->GetBoundingBox());
		m_centersQuadTree.Insert2(center, AABB(aabb.first, aabb.second));
	}
	std::cout << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;
}

void Map::GeneratePolygons()
{
	sf::Clock timer;

	GeneratePoints();
	std::cout << "Point placement: " << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;
	timer.restart();

	Triangulate(m_points);
	std::cout << "Triangulation: " << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;
	timer.restart();

	FinishInfo();
	std::cout << "Finishing touches: " << timer.getElapsedTime().asMicroseconds() / 1000.0 << " ms." << std::endl;
}

void Map::GenerateLand()
{
	m_noiseMap = new noise::module::Perlin();

	for (auto corner : m_corners)
	{
		if (!corner->IsInsideBoundingBox(m_mapWidth, m_mapHeight))
		{
			corner->m_border = true;
			corner->m_ocean = true;
			corner->m_water = true;
		}
	}

	for (auto corner : m_corners)
	{
		corner->m_water = !IsIsland(corner->m_position);
	}
}

std::vector<Edge*> Map::GetEdges() const
{
	return m_edges;
}

std::vector<Corner*> Map::GetCorners() const
{
	return m_corners;
}

std::vector<Center*> Map::GetCenters() const
{
	return m_centers;
}

Center* Map::GetCenterAt(Vector2 pos)
{
	Center* center = nullptr;
	std::vector<Center*> auxCenters = m_centersQuadTree.QueryRange(pos);

	if (auxCenters.size() > 0)
	{
		double minDist = Vector2(auxCenters[0]->m_position, pos).Length();
		center = auxCenters[0];

		for (auto auxCenter : auxCenters)
		{
			double newDist = Vector2(auxCenter->m_position, pos).Length();
			if (newDist < minDist)
			{
				minDist = newDist;
				center = auxCenter;
			}
		}
	}

	return center;
}

bool Map::IsIsland(Vector2 position)
{
	double waterThreshold = 0.075;

	if (position.x < m_mapWidth * waterThreshold || position.y < m_mapHeight * waterThreshold ||
		position.x > m_mapWidth * (1 - waterThreshold) || position.y > m_mapHeight * (1 - waterThreshold))
	{
		return false;
	}

	Vector2 centerPos = Vector2(m_mapWidth / 2.0, m_mapHeight / 2.0);
	position -= centerPos;

	double xCoord = (position.x / m_mapWidth) * 4;
	double yCoord = (position.y / m_mapHeight) * 4;
	double noiseVal = m_noiseMap->GetValue(xCoord, yCoord, m_zCoord);

	position /= std::min(m_mapWidth, m_mapHeight);
	double radius = position.Length();

	double factor = radius - 0.5;

	return noiseVal >= 0.3 * radius + factor;
}

void Map::CalculateDownslopes()
{
	for (auto c : m_corners)
	{
		Corner* d = c;
		for (auto q : c->m_corners)
		{
			if (q->m_elevation < d->m_elevation)
			{
				d = q;
			}
		}

		c->m_downslope = d;
	}
}

void Map::GenerateRivers()
{
	std::mt19937 mt_rand(HashString(m_seed));
	int numRivers = m_centers.size() / 3;

	for (int i = 0; i < numRivers; ++i)
	{
		Corner* q = m_corners[mt_rand() % m_corners.size()];

		if (q->m_ocean || q->m_elevation < 0.3 || q->m_elevation > 0.9)
		{
			continue;
		}

		while (!q->m_coast)
		{
			if (q == q->m_downslope)
			{
				break;
			}

			Edge* e = q->GetEdgeWith(q->m_downslope);
			e->m_riverVolume += 1;
			q->m_riverVolume += 1;
			q->m_downslope->m_riverVolume += 1;
			q = q->m_downslope;
		}
	}
}

void Map::AssignOceanCoastLand()
{
	std::queue<Center*> centersQueue;

	for (auto c : m_centers)
	{
		int adjacentWater = 0;

		for (auto q : c->m_centers)
		{
			if (q->m_border)
			{
				c->m_border = true;
				c->m_ocean = true;
				q->m_water = true;
				centersQueue.push(c);
			}

			if (q->m_water)
			{
				adjacentWater++;
			}
		}

		c->m_water = (c->m_ocean || adjacentWater >= c->m_corners.size() * 0.5);
	}

	while (!centersQueue.empty())
	{
		Center* c = centersQueue.front();
		centersQueue.pop();

		for (auto r : c->m_centers)
		{
			if (r->m_water && !r->m_ocean)
			{
				r->m_ocean = true;
				centersQueue.push(r);
			}
		}
	}

	for (auto p : m_centers)
	{
		int numOcean = 0;
		int numLand = 0;

		for (auto q : p->m_centers)
		{
			numOcean += static_cast<int>(q->m_ocean);
			numLand += static_cast<int>(!q->m_water);
		}

		p->m_coast = numLand > 0 && numOcean > 0;
	}

	for (auto c : m_corners)
	{
		int adjOcean = 0;
		int adjLand = 0;

		for (auto p : c->m_centers)
		{
			adjOcean += static_cast<int>(p->m_ocean);
			adjLand += static_cast<int>(!p->m_water);
		}

		c->m_ocean = adjOcean == c->m_centers.size();
		c->m_coast = adjLand > 0 && adjOcean > 0;
		c->m_water = c->m_border || (adjLand != c->m_centers.size() && !c->m_coast);
	}
}

void Map::RedistributeElevations()
{
	std::vector<Corner*> locations = GetLandCorners();
	const double SCALE_FACTOR = 1.05;

	sort(locations.begin(), locations.end(), &Corner::SortByElevation);

	for (int i = 0; i < locations.size(); ++i)
	{
		double y = static_cast<double>(i) / (locations.size() - 1);
		double x = sqrt(SCALE_FACTOR) - sqrt(SCALE_FACTOR * (1 - y));
		x = std::min(x, 1.0);
		locations[i]->m_elevation = x;
	}
}

void AssignCornerElevations();
void AssignPolygonElevations();
void RedistributeMoisture();
void AssignCornerMoisture();
void AssignPolygonMoisture();
void AssignBiomes();

void GeneratePoints();
void Triangulate(std::vector<DelaunayTriangulation::Vertex> points);
void FinishInfo();
void AddCenter(Center* c);
Center* GetCenter(Vector2 position);
void OrderPoints(std::vector<Corner*>& corners);

std::vector<Corner*> GetLandCorners();
std::vector<Corner*> GetLakeCorners();
void LloydRelaxation();
std::string CreateSeed(int length);

static unsigned int HashString(std::string seed);<|endoftext|>


<commit_before>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef FEATURE_STYLE_PROCESSOR_HPP
#define FEATURE_STYLE_PROCESSOR_HPP

// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>
#include <mapnik/memory_datasource.hpp>

#ifdef MAPNIK_DEBUG
//#include <mapnik/wall_clock_timer.hpp>
#endif
// boost
#include <boost/foreach.hpp>
//stl
#include <vector>

namespace mapnik
{

template <typename Processor>
class feature_style_processor
{
    /** Calls the renderer's process function,
      * \param output     Renderer
      * \param f          Feature to process
      * \param prj_trans  Projection
      * \param sym        Symbolizer object
      */
    struct symbol_dispatch : public boost::static_visitor<>
    {
        symbol_dispatch (Processor & output,
                         Feature const& f,
                         proj_transform const& prj_trans)
            : output_(output),
              f_(f),
              prj_trans_(prj_trans)  {}

        template <typename T>
        void operator () (T const& sym) const
        {
            output_.process(sym,f_,prj_trans_);
        }

        Processor & output_;
        Feature const& f_;
        proj_transform const& prj_trans_;
    };
public:
    explicit feature_style_processor(Map const& m, double scale_factor = 1.0)
        : m_(m),
          scale_factor_(scale_factor) {}

    void apply()
    {
#ifdef MAPNIK_DEBUG
        //mapnik::wall_clock_progress_timer t(std::clog, "map rendering took: ");
#endif
        Processor & p = static_cast<Processor&>(*this);
        p.start_map_processing(m_);

        try
        {
            projection proj(m_.srs()); // map projection

            Map::const_metawriter_iterator metaItr = m_.begin_metawriters();
            Map::const_metawriter_iterator metaItrEnd = m_.end_metawriters();
            for (;metaItr!=metaItrEnd; ++metaItr)
            {
                metaItr->second->set_size(m_.width(), m_.height());
                metaItr->second->set_map_srs(proj);
                metaItr->second->start(m_.metawriter_output_properties);
            }

            double scale_denom = mapnik::scale_denominator(m_,proj.is_geographic());
            scale_denom *= scale_factor_;
#ifdef MAPNIK_DEBUG
            std::clog << "scale denominator = " << scale_denom << "\n";
#endif
            BOOST_FOREACH ( layer const& lyr, m_.layers() )
            {
                if (lyr.isVisible(scale_denom))
                {
                    apply_to_layer(lyr, p, proj, scale_denom);
                }
            }

            metaItr = m_.begin_metawriters();
            for (;metaItr!=metaItrEnd; ++metaItr)
            {
                metaItr->second->stop();
            }
        }
        catch (proj_init_error& ex)
        {
            std::clog << "proj_init_error:" << ex.what() << "\n";
        }

        p.end_map_processing(m_);
    }
private:
    void apply_to_layer(layer const& lay, Processor & p,
                        projection const& proj0, double scale_denom)
    {
#ifdef MAPNIK_DEBUG
        //wall_clock_progress_timer timer(clog, "end layer rendering: ");
#endif
        boost::shared_ptr<datasource> ds = lay.datasource();
        if (!ds) {
            std::clog << "WARNING: No datasource for layer '" << lay.name() << "'\n";
            return;
        }
        p.start_layer_processing(lay);
        if (ds)
        {
            box2d<double> ext = m_.get_buffered_extent();
            projection proj1(lay.srs());
            proj_transform prj_trans(proj0,proj1);

            box2d<double> layer_ext = lay.envelope();

            double lx0 = layer_ext.minx();
            double ly0 = layer_ext.miny();
            double lz0 = 0.0;
            double lx1 = layer_ext.maxx();
            double ly1 = layer_ext.maxy();
            double lz1 = 0.0;
            // back project layers extent into main map projection
            prj_trans.backward(lx0,ly0,lz0);
            prj_trans.backward(lx1,ly1,lz1);

            // if no intersection then nothing to do for layer
            if ( lx0 > ext.maxx() || lx1 < ext.minx() || ly0 > ext.maxy() || ly1 < ext.miny() )
            {
                return;
            }

            // clip query bbox
            lx0 = std::max(ext.minx(),lx0);
            ly0 = std::max(ext.miny(),ly0);
            lx1 = std::min(ext.maxx(),lx1);
            ly1 = std::min(ext.maxy(),ly1);

            prj_trans.forward(lx0,ly0,lz0);
            prj_trans.forward(lx1,ly1,lz1);
            box2d<double> bbox(lx0,ly0,lx1,ly1);

            query::resolution_type res(m_.width()/m_.get_current_extent().width(),m_.height()/m_.get_current_extent().height());
            query q(bbox,res,scale_denom); //BBOX query

            std::vector<feature_type_style*> active_styles;
            std::set<std::string> names;
            attribute_collector collector(names);

            std::vector<std::string> const& style_names = lay.styles();
            // iterate through all named styles collecting active styles and attribute names
            BOOST_FOREACH(std::string const& style_name, style_names)
            {
                boost::optional<feature_type_style const&> style=m_.find_style(style_name);
                if (!style)
                {
                    std::clog << "WARNING: style '" << style_name << "' required for layer '" << lay.name() << "' does not exist.\n";
                    continue;
                }

                const std::vector<rule_type>& rules=(*style).get_rules();
                bool active_rules=false;

                BOOST_FOREACH(rule_type const& rule, rules)
                {
                    if (rule.active(scale_denom))
                    {
                        active_rules = true;
                        if (ds->type() == datasource::Vector)
                        {
                            collector(rule);
                        }
                        // TODO - in the future rasters should be able to be filtered.
                    }
                }
                if (active_rules)
                {
                    active_styles.push_back(const_cast<feature_type_style*>(&(*style)));
                }
            }

            // push all property names
            BOOST_FOREACH(std::string const& name, names)
            {
                q.add_property_name(name);
            }

            memory_datasource cache;
            bool cache_features = style_names.size()>1?true:false;
            bool first = true;

            BOOST_FOREACH (feature_type_style * style, active_styles)
            {
                std::vector<rule_type*> if_rules;
                std::vector<rule_type*> else_rules;

                std::vector<rule_type> const& rules=style->get_rules();

                BOOST_FOREACH(rule_type const& rule, rules)
                {
                    if (rule.active(scale_denom))
                    {
                        if (rule.has_else_filter())
                        {
                            else_rules.push_back(const_cast<rule_type*>(&rule));
                        }
                        else
                        {
                            if_rules.push_back(const_cast<rule_type*>(&rule));
                        }

                        if (ds->type() == datasource::Raster)
                        {
                            if (ds->params().get<double>("filter_factor",0.0) == 0.0)
                            {
                                rule_type::symbolizers const& symbols = rule.get_symbolizers();
                                rule_type::symbolizers::const_iterator symIter = symbols.begin();
                                rule_type::symbolizers::const_iterator symEnd = symbols.end();
                                for (;symIter != symEnd;++symIter)
                                {
                                    try
                                    {
                                        raster_symbolizer const& sym = boost::get<raster_symbolizer>(*symIter);
                                        std::string const& scaling = sym.get_scaling();
                                        if (scaling == "bilinear" || scaling == "bilinear8" )
                                        {
                                            // todo - allow setting custom value in symbolizer property?
                                            q.filter_factor(2.0);
                                        }
                                    }
                                    catch (const boost::bad_get &v)
                                    {
                                        // case where useless symbolizer is attached to raster layer
                                        //throw config_error("Invalid Symbolizer type supplied, only RasterSymbolizer is supported");
                                    }
                                }
                            }
                        }
                    }
                }

                // process features
                featureset_ptr fs;
                if (cache_features)
                {
                    if (first)
                    {
                        first = false;
                        fs = ds->features(q);
                    }
                    else
                    {
                        fs = cache.features(q);
                    }
                }
                else
                {
                    fs = ds->features(q);
                }

                if (fs)
                {
                    feature_ptr feature;
                    while ((feature = fs->next()))
                    {
                        bool do_else=true;

                        if (cache_features)
                        {
                            cache.push(feature);
                        }

                        BOOST_FOREACH(rule_type * rule, if_rules )
                        {
                            expression_ptr const& expr=rule->get_filter();
                            value_type result = boost::apply_visitor(evaluate<Feature,value_type>(*feature),*expr);
                            if (result.to_bool())
                            {
                                do_else=false;
                                rule_type::symbolizers const& symbols = rule->get_symbolizers();

                                // if the underlying renderer is not able to process the complete set of symbolizers,
                                // process one by one.
#ifdef SVG_RENDERER
                                if(!p.process(symbols,*feature,prj_trans))
#endif
                                {

                                    BOOST_FOREACH (symbolizer const& sym, symbols)
                                    {
                                        boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
                                    }
                                }
                            }
                        }
                        if (do_else)
                        {
                            BOOST_FOREACH( rule_type * rule, else_rules )
                            {
                                rule_type::symbolizers const& symbols = rule->get_symbolizers();
                                // if the underlying renderer is not able to process the complete set of symbolizers,
                                // process one by one.
#ifdef SVG_RENDERER
                                if(!p.process(symbols,*feature,prj_trans))
#endif
                                {
                                    BOOST_FOREACH (symbolizer const& sym, symbols)
                                    {
                                        boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
                                    }
                                }
                            }
                        }
                    }
                    cache_features = false;
                }
            }
        }

        p.end_layer_processing(lay);
    }

    Map const& m_;
    double scale_factor_;
};
}

#endif //FEATURE_STYLE_PROCESSOR_HPP
<commit_msg>+ don't process raster datasource + if src and dest projections are not matched<commit_after>/*****************************************************************************
 *
 * This file is part of Mapnik (c++ mapping toolkit)
 *
 * Copyright (C) 2006 Artem Pavlenko
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 *
 *****************************************************************************/

//$Id$

#ifndef FEATURE_STYLE_PROCESSOR_HPP
#define FEATURE_STYLE_PROCESSOR_HPP

// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/datasource.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/map.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/utils.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/scale_denominator.hpp>
#include <mapnik/memory_datasource.hpp>

#ifdef MAPNIK_DEBUG
//#include <mapnik/wall_clock_timer.hpp>
#endif
// boost
#include <boost/foreach.hpp>
//stl
#include <vector>

namespace mapnik
{

template <typename Processor>
class feature_style_processor
{
    /** Calls the renderer's process function,
      * \param output     Renderer
      * \param f          Feature to process
      * \param prj_trans  Projection
      * \param sym        Symbolizer object
      */
    struct symbol_dispatch : public boost::static_visitor<>
    {
        symbol_dispatch (Processor & output,
                         Feature const& f,
                         proj_transform const& prj_trans)
            : output_(output),
              f_(f),
              prj_trans_(prj_trans)  {}

        template <typename T>
        void operator () (T const& sym) const
        {
            output_.process(sym,f_,prj_trans_);
        }

        Processor & output_;
        Feature const& f_;
        proj_transform const& prj_trans_;
    };
public:
    explicit feature_style_processor(Map const& m, double scale_factor = 1.0)
        : m_(m),
          scale_factor_(scale_factor) {}

    void apply()
    {
#ifdef MAPNIK_DEBUG
        //mapnik::wall_clock_progress_timer t(std::clog, "map rendering took: ");
#endif
        Processor & p = static_cast<Processor&>(*this);
        p.start_map_processing(m_);

        try
        {
            projection proj(m_.srs()); // map projection

            Map::const_metawriter_iterator metaItr = m_.begin_metawriters();
            Map::const_metawriter_iterator metaItrEnd = m_.end_metawriters();
            for (;metaItr!=metaItrEnd; ++metaItr)
            {
                metaItr->second->set_size(m_.width(), m_.height());
                metaItr->second->set_map_srs(proj);
                metaItr->second->start(m_.metawriter_output_properties);
            }

            double scale_denom = mapnik::scale_denominator(m_,proj.is_geographic());
            scale_denom *= scale_factor_;
#ifdef MAPNIK_DEBUG
            std::clog << "scale denominator = " << scale_denom << "\n";
#endif
            BOOST_FOREACH ( layer const& lyr, m_.layers() )
            {
                if (lyr.isVisible(scale_denom))
                {
                    apply_to_layer(lyr, p, proj, scale_denom);
                }
            }

            metaItr = m_.begin_metawriters();
            for (;metaItr!=metaItrEnd; ++metaItr)
            {
                metaItr->second->stop();
            }
        }
        catch (proj_init_error& ex)
        {
            std::clog << "proj_init_error:" << ex.what() << "\n";
        }

        p.end_map_processing(m_);
    }
private:
    void apply_to_layer(layer const& lay, Processor & p,
                        projection const& proj0, double scale_denom)
    {
#ifdef MAPNIK_DEBUG
        //wall_clock_progress_timer timer(clog, "end layer rendering: ");
#endif
        boost::shared_ptr<datasource> ds = lay.datasource();
        if (!ds)
        {
            std::clog << "WARNING: No datasource for layer '" << lay.name() << "'\n";
            return;
        }

        p.start_layer_processing(lay);

        if (ds)
        {

            box2d<double> ext = m_.get_buffered_extent();
            projection proj1(lay.srs());
            proj_transform prj_trans(proj0,proj1);

            // todo: only display raster if src and dest proj are matched
            // todo: add raster re-projection as an optional feature
            if (ds->type() == datasource::Raster && !prj_trans.equal()) return;
            //

            box2d<double> layer_ext = lay.envelope();

            double lx0 = layer_ext.minx();
            double ly0 = layer_ext.miny();
            double lz0 = 0.0;
            double lx1 = layer_ext.maxx();
            double ly1 = layer_ext.maxy();
            double lz1 = 0.0;
            // back project layers extent into main map projection
            prj_trans.backward(lx0,ly0,lz0);
            prj_trans.backward(lx1,ly1,lz1);

            // if no intersection then nothing to do for layer
            if ( lx0 > ext.maxx() || lx1 < ext.minx() || ly0 > ext.maxy() || ly1 < ext.miny() )
            {
                return;
            }

            // clip query bbox
            lx0 = std::max(ext.minx(),lx0);
            ly0 = std::max(ext.miny(),ly0);
            lx1 = std::min(ext.maxx(),lx1);
            ly1 = std::min(ext.maxy(),ly1);

            prj_trans.forward(lx0,ly0,lz0);
            prj_trans.forward(lx1,ly1,lz1);
            box2d<double> bbox(lx0,ly0,lx1,ly1);

            query::resolution_type res(m_.width()/m_.get_current_extent().width(),m_.height()/m_.get_current_extent().height());
            query q(bbox,res,scale_denom); //BBOX query

            std::vector<feature_type_style*> active_styles;
            std::set<std::string> names;
            attribute_collector collector(names);

            std::vector<std::string> const& style_names = lay.styles();
            // iterate through all named styles collecting active styles and attribute names
            BOOST_FOREACH(std::string const& style_name, style_names)
            {
                boost::optional<feature_type_style const&> style=m_.find_style(style_name);
                if (!style)
                {
                    std::clog << "WARNING: style '" << style_name << "' required for layer '" << lay.name() << "' does not exist.\n";
                    continue;
                }

                const std::vector<rule_type>& rules=(*style).get_rules();
                bool active_rules=false;

                BOOST_FOREACH(rule_type const& rule, rules)
                {
                    if (rule.active(scale_denom))
                    {
                        active_rules = true;
                        if (ds->type() == datasource::Vector)
                        {
                            collector(rule);
                        }
                        // TODO - in the future rasters should be able to be filtered.
                    }
                }
                if (active_rules)
                {
                    active_styles.push_back(const_cast<feature_type_style*>(&(*style)));
                }
            }

            // push all property names
            BOOST_FOREACH(std::string const& name, names)
            {
                q.add_property_name(name);
            }

            memory_datasource cache;
            bool cache_features = style_names.size()>1?true:false;
            bool first = true;

            BOOST_FOREACH (feature_type_style * style, active_styles)
            {
                std::vector<rule_type*> if_rules;
                std::vector<rule_type*> else_rules;

                std::vector<rule_type> const& rules=style->get_rules();

                BOOST_FOREACH(rule_type const& rule, rules)
                {
                    if (rule.active(scale_denom))
                    {
                        if (rule.has_else_filter())
                        {
                            else_rules.push_back(const_cast<rule_type*>(&rule));
                        }
                        else
                        {
                            if_rules.push_back(const_cast<rule_type*>(&rule));
                        }

                        if (ds->type() == datasource::Raster )
                        {

                            if (ds->params().get<double>("filter_factor",0.0) == 0.0)
                            {
                                rule_type::symbolizers const& symbols = rule.get_symbolizers();
                                rule_type::symbolizers::const_iterator symIter = symbols.begin();
                                rule_type::symbolizers::const_iterator symEnd = symbols.end();
                                for (;symIter != symEnd;++symIter)
                                {
                                    try
                                    {
                                        raster_symbolizer const& sym = boost::get<raster_symbolizer>(*symIter);
                                        std::string const& scaling = sym.get_scaling();
                                        if (scaling == "bilinear" || scaling == "bilinear8" )
                                        {
                                            // todo - allow setting custom value in symbolizer property?
                                            q.filter_factor(2.0);
                                        }
                                    }
                                    catch (const boost::bad_get &v)
                                    {
                                        // case where useless symbolizer is attached to raster layer
                                        //throw config_error("Invalid Symbolizer type supplied, only RasterSymbolizer is supported");
                                    }
                                }
                            }
                        }
                    }
                }

                // process features
                featureset_ptr fs;
                if (cache_features)
                {
                    if (first)
                    {
                        first = false;
                        fs = ds->features(q);
                    }
                    else
                    {
                        fs = cache.features(q);
                    }
                }
                else
                {
                    fs = ds->features(q);
                }

                if (fs)
                {
                    feature_ptr feature;
                    while ((feature = fs->next()))
                    {
                        bool do_else=true;

                        if (cache_features)
                        {
                            cache.push(feature);
                        }

                        BOOST_FOREACH(rule_type * rule, if_rules )
                        {
                            expression_ptr const& expr=rule->get_filter();
                            value_type result = boost::apply_visitor(evaluate<Feature,value_type>(*feature),*expr);
                            if (result.to_bool())
                            {
                                do_else=false;
                                rule_type::symbolizers const& symbols = rule->get_symbolizers();

                                // if the underlying renderer is not able to process the complete set of symbolizers,
                                // process one by one.
#ifdef SVG_RENDERER
                                if(!p.process(symbols,*feature,prj_trans))
#endif
                                {

                                    BOOST_FOREACH (symbolizer const& sym, symbols)
                                    {
                                        boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
                                    }
                                }
                            }
                        }
                        if (do_else)
                        {
                            BOOST_FOREACH( rule_type * rule, else_rules )
                            {
                                rule_type::symbolizers const& symbols = rule->get_symbolizers();
                                // if the underlying renderer is not able to process the complete set of symbolizers,
                                // process one by one.
#ifdef SVG_RENDERER
                                if(!p.process(symbols,*feature,prj_trans))
#endif
                                {
                                    BOOST_FOREACH (symbolizer const& sym, symbols)
                                    {
                                        boost::apply_visitor(symbol_dispatch(p,*feature,prj_trans),sym);
                                    }
                                }
                            }
                        }
                    }
                    cache_features = false;
                }
            }
        }

        p.end_layer_processing(lay);
    }

    Map const& m_;
    double scale_factor_;
};
}

#endif //FEATURE_STYLE_PROCESSOR_HPP
<|endoftext|>


<commit_before>#include <string>
#include <vector>

namespace irods {
    std::string serialize_metadata( const std::vector<std::string>& metadata );
    std::vector<std::string> deserialize_metadata( const std::string& metadata );
}

extern "C" {
    char* serialize_metadata_c( const char** metadata, size_t metadata_len );
}
<commit_msg>[#2064] added guards to metadata_serialization.hpp<commit_after>#ifndef IRODS_METADATA_SERIALIZATION_HPP__
#define IRODS_METADATA_SERIALIZATION_HPP__
#include <string>
#include <vector>

#ifdef __cplusplus
namespace irods {
    std::string serialize_metadata( const std::vector<std::string>& metadata );
    std::vector<std::string> deserialize_metadata( const std::string& metadata );
}
#endif

extern "C" {
    char* serialize_metadata_c( const char** metadata, size_t metadata_len );
}
#endif
<|endoftext|>


<commit_before>#ifndef ALEPH_PERSISTENT_HOMOLOGY_ALGORITHMS_STANDARD_HH__
#define ALEPH_PERSISTENT_HOMOLOGY_ALGORITHMS_STANDARD_HH__

#include <aleph/topology/BoundaryMatrix.hh>

#include <tuple>
#include <vector>

namespace aleph
{

namespace persistentHomology
{

namespace algorithms
{

class Standard
{
public:
  template <class Representation> void operator()( topology::BoundaryMatrix<Representation>& M )
  {
    using Index = typename Representation::Index;

    auto numColumns = M.getNumColumns();

    std::vector< std::pair<Index, bool> > lut( static_cast<std::size_t>( numColumns ),
                                               std::make_pair(0, false) );

    for( Index j = 0; j < numColumns; j++ )
    {
      Index i;
      bool valid = false;

      std::tie( i, valid ) = M.getMaximumIndex( j );
      while( valid && lut[ static_cast<std::size_t>(i) ].second )
      {
        M.addColumns( lut[ static_cast<std::size_t>(i) ].first, j );
        std::tie( i, valid ) = M.getMaximumIndex( j );
      }

      if( valid )
        lut[ static_cast<std::size_t>(i) ] = std::make_pair( j, true );
    }
  }
};

} // namespace algorithms

} // namespace persistentHomology

} // namespace aleph

#endif
<commit_msg>Providing additional standard reduction algorithm for rectangular matrices<commit_after>#ifndef ALEPH_PERSISTENT_HOMOLOGY_ALGORITHMS_STANDARD_HH__
#define ALEPH_PERSISTENT_HOMOLOGY_ALGORITHMS_STANDARD_HH__

#include <aleph/topology/BoundaryMatrix.hh>

#include <tuple>
#include <vector>

namespace aleph
{

namespace persistentHomology
{

namespace algorithms
{

class Standard
{
public:
  template <class Representation> void operator()( topology::BoundaryMatrix<Representation>& M )
  {
    using Index = typename Representation::Index;

    auto numColumns = M.getNumColumns();

    std::vector< std::pair<Index, bool> > lut( static_cast<std::size_t>( numColumns ),
                                               std::make_pair(0, false) );

    for( Index j = 0; j < numColumns; j++ )
    {
      Index i;
      bool valid = false;

      std::tie( i, valid ) = M.getMaximumIndex( j );
      while( valid && lut[ static_cast<std::size_t>(i) ].second )
      {
        M.addColumns( lut[ static_cast<std::size_t>(i) ].first, j );
        std::tie( i, valid ) = M.getMaximumIndex( j );
      }

      if( valid )
        lut[ static_cast<std::size_t>(i) ] = std::make_pair( j, true );
    }
  }
};

class StandardRectangular
{
public:
  template <class Representation> void operator()( topology::BoundaryMatrix<Representation>& M )
  {
    using Index = typename Representation::Index;

    auto numColumns = M.getNumColumns();

    std::vector< std::pair<Index, bool> > lut( static_cast<std::size_t>( numColumns ),
                                               std::make_pair(0, false) );

    for( Index j = 0; j < numColumns; j++ )
    {
      Index i;
      bool valid = false;

      std::tie( i, valid ) = M.getMaximumIndex( j );

      if( i >= numColumns )
        continue;

      while( valid && lut[ static_cast<std::size_t>(i) ].second )
      {
        M.addColumns( lut[ static_cast<std::size_t>(i) ].first, j );
        std::tie( i, valid ) = M.getMaximumIndex( j );
      }

      if( valid )
        lut[ static_cast<std::size_t>(i) ] = std::make_pair( j, true );
    }
  }
};

} // namespace algorithms

} // namespace persistentHomology

} // namespace aleph

#endif
<|endoftext|>


<commit_before>// Тесты:
// 1. Завел числа в таком порядке:
// 11 7 14 3 9 1 5 8 10 0 2 4 6. Получил дерево значений в возрастающем порядке:
// 0 1 2 3 4 5 6 7 8 9 10 11 14 и наоборот в убывающем. Удалял вершины (4 варианта удаления):
// 1. (две дочерние вершины пусты): просто занудение вершины, например, удаляем 14.
// 2. (левая дочерняя вершина не пуста, правая пуста): переносим эту левую вершину выше на 1 уровень.
// 3. (правая дочерняя вершина не пуста, левая пуста): аналогично с 2 вариантом.
// 4. (обе вершины не пусты): переносим самую наименьшую (самую левую) дочернюю вершину из правых
// относительно рассматриваемой вершины вершин на место удаляемой.
// Далее можно проверить, есть ли значение в дереве. Для этого производим сравнения и выводим результат:
// если есть сопадение или его нет. Например: в исходном дереве вершина 7 будет, а вершина 12 - не будет
// выводиться.

#include "Tree.h"
#include <iostream>

using namespace std;

int main()
{
	int element = 0;
	int command = -1;
	Node *MyTree = nullptr;
	while (command != 0)
	{
		cout << "Write command: ";
		cin >> command;
		switch (command)
		{
		case 0:
		{
			cout << "Ending of the programm." << endl;
			break;
		}
		case 1:
		{
			cout << "Write element: ";
			cin >> element;
			add(element, MyTree);
			continue;
		}
		case 2:
		{
			cout << "Write element: ";
			cin >> element;
			deleteElement(MyTree, element);
			continue;
		}
		case 3:
		{
			cout << "Write element: ";
			cin >> element;
			IfInSet(element, MyTree);
			continue;
		}
		case 4:
		{
			int variant = 0;
			cout << "How do you want to see the elements?(1-in ascending order,2-in descending order)";
			cin >> variant;
			if (variant == 1)
			{
				Show(MyTree, 1);
			}
			else
			{
				if (variant == 2)
				{
					Show(MyTree, 2);
				}
				else
				{
					cout << "Unknown variant.";
				}
			}
			cout << endl;
			continue;
		}
		default:
		{
			cout << "Unknown command." << endl;
			continue;
		}
		}
	}
	deleteTree(MyTree);
	return 0;
}
<commit_msg>Delete 8_2.cpp<commit_after><|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: XMLPropertyBackpatcher.cxx,v $
 *
 *  $Revision: 1.8 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 16:03:41 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"

#ifndef _COM_SUN_STAR_BEANS_XPROPERTYSET_HPP_
#include <com/sun/star/beans/XPropertySet.hpp>
#endif

#ifndef _COM_SUN_STAR_UNO_REFERENCE_H_
#include <com/sun/star/uno/Reference.h>
#endif

#ifndef _RTL_USTRING
#include <rtl/ustring.hxx>
#endif

#ifndef _TOOLS_DEBUG_HXX
#include <tools/debug.hxx>
#endif

#ifndef _XMLOFF_XMLPROPERTYBACKPATCHER_HXX
#include "XMLPropertyBackpatcher.hxx"
#endif

#ifndef _XMLOFF_TEXTIMP_HXX_
#include <xmloff/txtimp.hxx>    // XMLTextImportHelper partially implemented here
#endif

using ::rtl::OUString;
using ::std::vector;
using ::std::map;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Any;
using ::com::sun::star::beans::XPropertySet;

template<class A>
XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
    const ::rtl::OUString& sPropName)
:   sPropertyName(sPropName)
,   bDefaultHandling(sal_False)
,   bPreserveProperty(sal_False)
,   sPreservePropertyName()
{
}

template<class A>
XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
    const OUString& sPropName,
    const OUString& sPreserveName,
    sal_Bool bDefault,
    A aDef)
:   sPropertyName(sPropName)
,   bDefaultHandling(bDefault)
,   bPreserveProperty(sPreserveName.getLength()>0)
,   sPreservePropertyName(sPreserveName)
,   aDefault(aDef)
{
}

template<class A>
XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
    const sal_Char* pPropName)
:   bDefaultHandling(sal_False)
,   bPreserveProperty(sal_False)
{
    DBG_ASSERT(pPropName != NULL, "need property name");
    sPropertyName = OUString::createFromAscii(pPropName);
}

template<class A>
XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
    const sal_Char* pPropName,
    const sal_Char* pPreservePropName,
    sal_Bool bDefault,
    A aDef)
:   bDefaultHandling(bDefault)
,   bPreserveProperty(pPreservePropName != NULL)
,   aDefault(aDef)
{
    DBG_ASSERT(pPropName != NULL, "need property name");
    sPropertyName = OUString::createFromAscii(pPropName);
    if (pPreservePropName != NULL)
    {
        sPreservePropertyName = OUString::createFromAscii(pPreservePropName);
    }
}

template<class A>
XMLPropertyBackpatcher<A>::~XMLPropertyBackpatcher()
{
    SetDefault();
}

template<class A>
void XMLPropertyBackpatcher<A>::ResolveId(
    const OUString& sName,
    A aValue)
{
    // insert ID into ID map
    aIDMap[sName] = aValue;

    // backpatch old references, if backpatch list exists
    if (aBackpatchListMap.count(sName))
    {
        // aah, we have a backpatch list!
        BackpatchListType* pList =
            (BackpatchListType*)aBackpatchListMap[sName];

        // a) remove list from list map
        aBackpatchListMap.erase(sName);

        // b) for every item, set SequenceNumber
        //    (and preserve Property, if appropriate)
        Any aAny;
        aAny <<= aValue;
        if (bPreserveProperty)
        {
            // preserve version
            for(BackpatchListType::iterator aIter = pList->begin();
                aIter != pList->end();
                aIter++)
            {
                Reference<XPropertySet> xProp = (*aIter);
                Any aPres = xProp->getPropertyValue(sPreservePropertyName);
                xProp->setPropertyValue(sPropertyName, aAny);
                xProp->setPropertyValue(sPreservePropertyName, aPres);
            }
        }
        else
        {
            // without preserve
            for(BackpatchListType::iterator aIter = pList->begin();
                aIter != pList->end();
                aIter++)
            {
                (*aIter)->setPropertyValue(sPropertyName, aAny);
            }
        }

        // c) delete list
        delete pList;
    }
    // else: no backpatch list -> then we're finished
}

template<class A>
void XMLPropertyBackpatcher<A>::SetProperty(
    const Reference<XPropertySet> & xPropSet,
    const OUString& sName)
{
    Reference<XPropertySet> xNonConstPropSet(xPropSet);
    SetProperty(xNonConstPropSet, sName);
}

template<class A>
void XMLPropertyBackpatcher<A>::SetProperty(
    Reference<XPropertySet> & xPropSet,
    const OUString& sName)
{
    if (aIDMap.count(sName))
    {
        // we know this ID -> set property
        Any aAny;
        aAny <<= aIDMap[sName];
        xPropSet->setPropertyValue(sPropertyName, aAny);
    }
    else
    {
        // ID unknown -> into backpatch list for later fixup
        if (! aBackpatchListMap.count(sName))
        {
            // create backpatch list for this name
            BackpatchListType* pTmp = new BackpatchListType() ;
            aBackpatchListMap[sName] = (void*)pTmp;
        }

        // insert footnote
        ((BackpatchListType*)aBackpatchListMap[sName])->push_back(xPropSet);
    }
}

template<class A>
void XMLPropertyBackpatcher<A>::SetDefault()
{
    if (bDefaultHandling)
    {
        // not implemented yet
    }
}

// force instantiation of templates
template class XMLPropertyBackpatcher<sal_Int16>;
template class XMLPropertyBackpatcher<OUString>;

//
// XMLTextImportHelper
//
// Code from XMLTextImportHelper using the XMLPropertyBackpatcher is
// implemented here. The reason is that in the unxsols2 environment,
// all templates are instatiated as file local (switch
// -instances=static), and thus are not accessible from the outside.
//
// The previous solution was to force additional instantiation of
// XMLPropertyBackpatcher in txtimp.cxx. This solution combines all
// usage of the XMLPropertyBackpatcher in XMLPropertyBackpatcher.cxx
// instead.
//

XMLPropertyBackpatcher<sal_Int16>& XMLTextImportHelper::GetFootnoteBP()
{
    if (NULL == pFootnoteBackpatcher)
    {
        pFootnoteBackpatcher =
            new XMLPropertyBackpatcher<sal_Int16>(sSequenceNumber);
    }
    return *pFootnoteBackpatcher;
}

XMLPropertyBackpatcher<sal_Int16>& XMLTextImportHelper::GetSequenceIdBP()
{
    if (NULL == pSequenceIdBackpatcher)
    {
        pSequenceIdBackpatcher =
            new XMLPropertyBackpatcher<sal_Int16>(sSequenceNumber);
    }
    return *pSequenceIdBackpatcher;
}

XMLPropertyBackpatcher<OUString>& XMLTextImportHelper::GetSequenceNameBP()
{
    if (NULL == pSequenceNameBackpatcher)
    {
        pSequenceNameBackpatcher =
            new XMLPropertyBackpatcher<OUString>(sSourceName);
    }
    return *pSequenceNameBackpatcher;
}

void XMLTextImportHelper::InsertFootnoteID(
    const OUString& sXMLId,
    sal_Int16 nAPIId)
{
    GetFootnoteBP().ResolveId(sXMLId, nAPIId);
}

void XMLTextImportHelper::ProcessFootnoteReference(
    const OUString& sXMLId,
    const Reference<XPropertySet> & xPropSet)
{
    GetFootnoteBP().SetProperty(xPropSet, sXMLId);
}

void XMLTextImportHelper::InsertSequenceID(
    const OUString& sXMLId,
    const OUString& sName,
    sal_Int16 nAPIId)
{
    GetSequenceIdBP().ResolveId(sXMLId, nAPIId);
    GetSequenceNameBP().ResolveId(sXMLId, sName);
}

void XMLTextImportHelper::ProcessSequenceReference(
    const OUString& sXMLId,
    const Reference<XPropertySet> & xPropSet)
{
    GetSequenceIdBP().SetProperty(xPropSet, sXMLId);
    GetSequenceNameBP().SetProperty(xPropSet, sXMLId);
}

void XMLTextImportHelper::_FinitBackpatcher()
{
    delete pFootnoteBackpatcher;
    delete pSequenceIdBackpatcher;
    delete pSequenceNameBackpatcher;
}
<commit_msg>INTEGRATION: CWS changefileheader (1.8.162); FILE MERGED 2008/04/01 16:10:09 thb 1.8.162.3: #i85898# Stripping all external header guards 2008/04/01 13:05:28 thb 1.8.162.2: #i85898# Stripping all external header guards 2008/03/31 16:28:35 rt 1.8.162.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: XMLPropertyBackpatcher.cxx,v $
 * $Revision: 1.9 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org 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.
 *
 * OpenOffice.org 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
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_xmloff.hxx"
#include <com/sun/star/beans/XPropertySet.hpp>
#include <com/sun/star/uno/Reference.h>

#ifndef _RTL_USTRING
#include <rtl/ustring.hxx>
#endif
#include <tools/debug.hxx>
#include "XMLPropertyBackpatcher.hxx"
#include <xmloff/txtimp.hxx>    // XMLTextImportHelper partially implemented here

using ::rtl::OUString;
using ::std::vector;
using ::std::map;
using ::com::sun::star::uno::Reference;
using ::com::sun::star::uno::Any;
using ::com::sun::star::beans::XPropertySet;

template<class A>
XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
    const ::rtl::OUString& sPropName)
:   sPropertyName(sPropName)
,   bDefaultHandling(sal_False)
,   bPreserveProperty(sal_False)
,   sPreservePropertyName()
{
}

template<class A>
XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
    const OUString& sPropName,
    const OUString& sPreserveName,
    sal_Bool bDefault,
    A aDef)
:   sPropertyName(sPropName)
,   bDefaultHandling(bDefault)
,   bPreserveProperty(sPreserveName.getLength()>0)
,   sPreservePropertyName(sPreserveName)
,   aDefault(aDef)
{
}

template<class A>
XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
    const sal_Char* pPropName)
:   bDefaultHandling(sal_False)
,   bPreserveProperty(sal_False)
{
    DBG_ASSERT(pPropName != NULL, "need property name");
    sPropertyName = OUString::createFromAscii(pPropName);
}

template<class A>
XMLPropertyBackpatcher<A>::XMLPropertyBackpatcher(
    const sal_Char* pPropName,
    const sal_Char* pPreservePropName,
    sal_Bool bDefault,
    A aDef)
:   bDefaultHandling(bDefault)
,   bPreserveProperty(pPreservePropName != NULL)
,   aDefault(aDef)
{
    DBG_ASSERT(pPropName != NULL, "need property name");
    sPropertyName = OUString::createFromAscii(pPropName);
    if (pPreservePropName != NULL)
    {
        sPreservePropertyName = OUString::createFromAscii(pPreservePropName);
    }
}

template<class A>
XMLPropertyBackpatcher<A>::~XMLPropertyBackpatcher()
{
    SetDefault();
}

template<class A>
void XMLPropertyBackpatcher<A>::ResolveId(
    const OUString& sName,
    A aValue)
{
    // insert ID into ID map
    aIDMap[sName] = aValue;

    // backpatch old references, if backpatch list exists
    if (aBackpatchListMap.count(sName))
    {
        // aah, we have a backpatch list!
        BackpatchListType* pList =
            (BackpatchListType*)aBackpatchListMap[sName];

        // a) remove list from list map
        aBackpatchListMap.erase(sName);

        // b) for every item, set SequenceNumber
        //    (and preserve Property, if appropriate)
        Any aAny;
        aAny <<= aValue;
        if (bPreserveProperty)
        {
            // preserve version
            for(BackpatchListType::iterator aIter = pList->begin();
                aIter != pList->end();
                aIter++)
            {
                Reference<XPropertySet> xProp = (*aIter);
                Any aPres = xProp->getPropertyValue(sPreservePropertyName);
                xProp->setPropertyValue(sPropertyName, aAny);
                xProp->setPropertyValue(sPreservePropertyName, aPres);
            }
        }
        else
        {
            // without preserve
            for(BackpatchListType::iterator aIter = pList->begin();
                aIter != pList->end();
                aIter++)
            {
                (*aIter)->setPropertyValue(sPropertyName, aAny);
            }
        }

        // c) delete list
        delete pList;
    }
    // else: no backpatch list -> then we're finished
}

template<class A>
void XMLPropertyBackpatcher<A>::SetProperty(
    const Reference<XPropertySet> & xPropSet,
    const OUString& sName)
{
    Reference<XPropertySet> xNonConstPropSet(xPropSet);
    SetProperty(xNonConstPropSet, sName);
}

template<class A>
void XMLPropertyBackpatcher<A>::SetProperty(
    Reference<XPropertySet> & xPropSet,
    const OUString& sName)
{
    if (aIDMap.count(sName))
    {
        // we know this ID -> set property
        Any aAny;
        aAny <<= aIDMap[sName];
        xPropSet->setPropertyValue(sPropertyName, aAny);
    }
    else
    {
        // ID unknown -> into backpatch list for later fixup
        if (! aBackpatchListMap.count(sName))
        {
            // create backpatch list for this name
            BackpatchListType* pTmp = new BackpatchListType() ;
            aBackpatchListMap[sName] = (void*)pTmp;
        }

        // insert footnote
        ((BackpatchListType*)aBackpatchListMap[sName])->push_back(xPropSet);
    }
}

template<class A>
void XMLPropertyBackpatcher<A>::SetDefault()
{
    if (bDefaultHandling)
    {
        // not implemented yet
    }
}

// force instantiation of templates
template class XMLPropertyBackpatcher<sal_Int16>;
template class XMLPropertyBackpatcher<OUString>;

//
// XMLTextImportHelper
//
// Code from XMLTextImportHelper using the XMLPropertyBackpatcher is
// implemented here. The reason is that in the unxsols2 environment,
// all templates are instatiated as file local (switch
// -instances=static), and thus are not accessible from the outside.
//
// The previous solution was to force additional instantiation of
// XMLPropertyBackpatcher in txtimp.cxx. This solution combines all
// usage of the XMLPropertyBackpatcher in XMLPropertyBackpatcher.cxx
// instead.
//

XMLPropertyBackpatcher<sal_Int16>& XMLTextImportHelper::GetFootnoteBP()
{
    if (NULL == pFootnoteBackpatcher)
    {
        pFootnoteBackpatcher =
            new XMLPropertyBackpatcher<sal_Int16>(sSequenceNumber);
    }
    return *pFootnoteBackpatcher;
}

XMLPropertyBackpatcher<sal_Int16>& XMLTextImportHelper::GetSequenceIdBP()
{
    if (NULL == pSequenceIdBackpatcher)
    {
        pSequenceIdBackpatcher =
            new XMLPropertyBackpatcher<sal_Int16>(sSequenceNumber);
    }
    return *pSequenceIdBackpatcher;
}

XMLPropertyBackpatcher<OUString>& XMLTextImportHelper::GetSequenceNameBP()
{
    if (NULL == pSequenceNameBackpatcher)
    {
        pSequenceNameBackpatcher =
            new XMLPropertyBackpatcher<OUString>(sSourceName);
    }
    return *pSequenceNameBackpatcher;
}

void XMLTextImportHelper::InsertFootnoteID(
    const OUString& sXMLId,
    sal_Int16 nAPIId)
{
    GetFootnoteBP().ResolveId(sXMLId, nAPIId);
}

void XMLTextImportHelper::ProcessFootnoteReference(
    const OUString& sXMLId,
    const Reference<XPropertySet> & xPropSet)
{
    GetFootnoteBP().SetProperty(xPropSet, sXMLId);
}

void XMLTextImportHelper::InsertSequenceID(
    const OUString& sXMLId,
    const OUString& sName,
    sal_Int16 nAPIId)
{
    GetSequenceIdBP().ResolveId(sXMLId, nAPIId);
    GetSequenceNameBP().ResolveId(sXMLId, sName);
}

void XMLTextImportHelper::ProcessSequenceReference(
    const OUString& sXMLId,
    const Reference<XPropertySet> & xPropSet)
{
    GetSequenceIdBP().SetProperty(xPropSet, sXMLId);
    GetSequenceNameBP().SetProperty(xPropSet, sXMLId);
}

void XMLTextImportHelper::_FinitBackpatcher()
{
    delete pFootnoteBackpatcher;
    delete pSequenceIdBackpatcher;
    delete pSequenceNameBackpatcher;
}
<|endoftext|>