<commit_before>#include "runtime_internal.h"
#include "HalideRuntime.h"
#include "scoped_mutex_lock.h"

// Note: The profiler thread may out-live any valid user_context, or
// be used across many different user_contexts, so nothing it calls
// can depend on the user context.

extern "C" {
// Returns the address of the global halide_profiler state
WEAK halide_profiler_state *halide_profiler_get_state() {
    static halide_profiler_state s = {{{0}}, NULL, 1000000, 0, 0, false};
    return &s;
}
}

namespace Halide { namespace Runtime { namespace Internal {

WEAK halide_profiler_pipeline_stats *find_or_create_pipeline(const char *pipeline_name, int num_funcs, const char **func_names) {
    halide_profiler_state *s = halide_profiler_get_state();

    for (halide_profiler_pipeline_stats *p = s->pipelines; p;
         p = (halide_profiler_pipeline_stats *)(p->next)) {
        // The same pipeline will deliver the same global constant
        // string, so they can be compared by pointer.
        if (p->name == pipeline_name &&
            p->num_funcs == num_funcs) {
            return p;
        }
    }
    // Create a new pipeline stats entry.
    halide_profiler_pipeline_stats *p =
        (halide_profiler_pipeline_stats *)halide_malloc(NULL, sizeof(halide_profiler_pipeline_stats));
    if (!p) return NULL;
    p->next = s->pipelines;
    p->name = pipeline_name;
    p->first_func_id = s->first_free_id;
    p->num_funcs = num_funcs;
    p->runs = 0;
    p->time = 0;
    p->samples = 0;
    p->funcs = (halide_profiler_func_stats *)halide_malloc(NULL, num_funcs * sizeof(halide_profiler_func_stats));
    if (!p->funcs) {
        halide_free(NULL, p);
        return NULL;
    }
    for (int i = 0; i < num_funcs; i++) {
        p->funcs[i].time = 0;
        p->funcs[i].name = func_names[i];
    }
    s->first_free_id += num_funcs;
    s->pipelines = p;
    return p;
}

WEAK void bill_func(halide_profiler_state *s, int func_id, uint64_t time) {
    halide_profiler_pipeline_stats *p_prev = NULL;
    for (halide_profiler_pipeline_stats *p = s->pipelines; p;
         p = (halide_profiler_pipeline_stats *)(p->next)) {
        if (func_id >= p->first_func_id && func_id < p->first_func_id + p->num_funcs) {
            if (p_prev) {
                // Bubble the pipeline to the top to speed up future queries.
                p_prev->next = (halide_profiler_pipeline_stats *)(p->next);
                p->next = s->pipelines;
                s->pipelines = p;
            }
            p->funcs[func_id - p->first_func_id].time += time;
            p->time += time;
            p->samples++;
            return;
        }
        p_prev = p;
    }
    // panic!
    print(NULL)
        << "Internal error in profiler: \n"
        << "Could not find pipeline for func_id " << func_id << "\n"
        << "Pipelines:\n";
    for (halide_profiler_pipeline_stats *p = s->pipelines; p; p = (halide_profiler_pipeline_stats *)(p->next)) {
        print(NULL) << p->name << " : " << p->first_func_id << ", " << p->num_funcs << "\n";
    }
    error(NULL) << "Could not proceed.\n";
}

// TODO: make this something like halide_nanosleep so that it can be implemented per OS
extern "C" void usleep(int);

WEAK void *sampling_profiler_thread(void *) {
    halide_profiler_state *s = halide_profiler_get_state();

    // grab the lock
    halide_mutex_lock(&s->lock);

    while (s->current_func != halide_profiler_please_stop) {

        uint64_t t1 = halide_current_time_ns(NULL);
        uint64_t t = t1;
        while (1) {
            uint64_t t_now = halide_current_time_ns(NULL);
            int func = s->current_func;
            if (func == halide_profiler_please_stop) {
                break;
            } else if (func >= 0) {
               // Assume all time since I was last awake is due to
               // the currently running func.
               bill_func(s, func, t_now - t);
            }
            t = t_now;

            // Release the lock, sleep, reacquire.
            uint64_t sleep_ns = s->sleep_time;
            halide_mutex_unlock(&s->lock);
            usleep(sleep_ns/1000);
            halide_mutex_lock(&s->lock);
        }
    }

    s->started = false;

    halide_mutex_unlock(&s->lock);
    return NULL;
}

}}}

extern "C" {

// Returns a token identifying this pipeline instance.
WEAK int halide_profiler_pipeline_start(void *user_context,
                                        const char *pipeline_name,
                                        int num_funcs,
                                        const char **func_names) {
    halide_profiler_state *s = halide_profiler_get_state();

    ScopedMutexLock lock(&s->lock);

    if (!s->started) {
        halide_spawn_thread(user_context, sampling_profiler_thread, NULL);
        s->started = true;
    }

    halide_profiler_pipeline_stats *p =
        find_or_create_pipeline(pipeline_name, num_funcs, func_names);
    if (!p) {
        // Allocating space to track the statistics failed.
        return halide_error_out_of_memory(user_context);
    }
    p->runs++;

    return p->first_func_id;
}

WEAK void halide_profiler_report(void *user_context) {
    halide_profiler_state *s = halide_profiler_get_state();

    char line_buf[160];
    Printer<StringStreamPrinter, sizeof(line_buf)> sstr(user_context, line_buf);

    ScopedMutexLock lock(&s->lock);

    for (halide_profiler_pipeline_stats *p = s->pipelines; p;
         p = (halide_profiler_pipeline_stats *)(p->next)) {
        float t = p->time / 1000000.0f;
        if (!p->runs) continue;
        sstr.clear();
        sstr << p->name
             << "  total time: " << t << " ms"
             << "  samples: " << p->samples
             << "  runs: " << p->runs
             << "  time per run: " << t / p->runs << " ms\n";
        halide_print(user_context, sstr.str());
        if (p->time) {
            for (int i = 0; i < p->num_funcs; i++) {
                sstr.clear();
                halide_profiler_func_stats *fs = p->funcs + i;

                // The first func is always a catch-all overhead
                // slot. Only report overhead time if it's non-zero
                if (i == 0 && fs->time == 0) continue;

                sstr << "  " << fs->name << ": ";
                while (sstr.size() < 25) sstr << " ";

                float ft = fs->time / (p->runs * 1000000.0f);
                sstr << ft << "ms";
                while (sstr.size() < 40) sstr << " ";

                int percent = fs->time / (p->time / 100);
                sstr << "(" << percent << "%)\n";

                halide_print(user_context, sstr.str());
            }
        }
    }
}

WEAK void halide_profiler_reset() {
    halide_profiler_state *s = halide_profiler_get_state();

    ScopedMutexLock lock(&s->lock);

    while (s->pipelines) {
        halide_profiler_pipeline_stats *p = s->pipelines;
        s->pipelines = (halide_profiler_pipeline_stats *)(p->next);
        halide_free(NULL, p->funcs);
        halide_free(NULL, p);
    }
    s->first_free_id = 0;
}

namespace {
__attribute__((destructor))
WEAK void halide_profiler_shutdown() {
    halide_profiler_state *s = halide_profiler_get_state();
    s->current_func = halide_profiler_please_stop;
    do {
        // Memory barrier.
        __sync_synchronize(&s->started,
                           &s->current_func);
    } while (s->started);
    s->current_func = halide_profiler_outside_of_halide;

    // print results
    halide_profiler_report(NULL);

    // free memory
    halide_profiler_reset();
}
}

WEAK void halide_profiler_pipeline_end(void *user_context, void *state) {
    ((halide_profiler_state *)state)->current_func = halide_profiler_outside_of_halide;
}

}
<commit_msg>Shut down the profiler more conservatively<commit_after>#include "runtime_internal.h"
#include "HalideRuntime.h"
#include "scoped_mutex_lock.h"

// Note: The profiler thread may out-live any valid user_context, or
// be used across many different user_contexts, so nothing it calls
// can depend on the user context.

extern "C" {
// Returns the address of the global halide_profiler state
WEAK halide_profiler_state *halide_profiler_get_state() {
    static halide_profiler_state s = {{{0}}, NULL, 1000000, 0, 0, false};
    return &s;
}
}

namespace Halide { namespace Runtime { namespace Internal {

WEAK halide_profiler_pipeline_stats *find_or_create_pipeline(const char *pipeline_name, int num_funcs, const char **func_names) {
    halide_profiler_state *s = halide_profiler_get_state();

    for (halide_profiler_pipeline_stats *p = s->pipelines; p;
         p = (halide_profiler_pipeline_stats *)(p->next)) {
        // The same pipeline will deliver the same global constant
        // string, so they can be compared by pointer.
        if (p->name == pipeline_name &&
            p->num_funcs == num_funcs) {
            return p;
        }
    }
    // Create a new pipeline stats entry.
    halide_profiler_pipeline_stats *p =
        (halide_profiler_pipeline_stats *)halide_malloc(NULL, sizeof(halide_profiler_pipeline_stats));
    if (!p) return NULL;
    p->next = s->pipelines;
    p->name = pipeline_name;
    p->first_func_id = s->first_free_id;
    p->num_funcs = num_funcs;
    p->runs = 0;
    p->time = 0;
    p->samples = 0;
    p->funcs = (halide_profiler_func_stats *)halide_malloc(NULL, num_funcs * sizeof(halide_profiler_func_stats));
    if (!p->funcs) {
        halide_free(NULL, p);
        return NULL;
    }
    for (int i = 0; i < num_funcs; i++) {
        p->funcs[i].time = 0;
        p->funcs[i].name = func_names[i];
    }
    s->first_free_id += num_funcs;
    s->pipelines = p;
    return p;
}

WEAK void bill_func(halide_profiler_state *s, int func_id, uint64_t time) {
    halide_profiler_pipeline_stats *p_prev = NULL;
    for (halide_profiler_pipeline_stats *p = s->pipelines; p;
         p = (halide_profiler_pipeline_stats *)(p->next)) {
        if (func_id >= p->first_func_id && func_id < p->first_func_id + p->num_funcs) {
            if (p_prev) {
                // Bubble the pipeline to the top to speed up future queries.
                p_prev->next = (halide_profiler_pipeline_stats *)(p->next);
                p->next = s->pipelines;
                s->pipelines = p;
            }
            p->funcs[func_id - p->first_func_id].time += time;
            p->time += time;
            p->samples++;
            return;
        }
        p_prev = p;
    }
    // panic!
    print(NULL)
        << "Internal error in profiler: \n"
        << "Could not find pipeline for func_id " << func_id << "\n"
        << "Pipelines:\n";
    for (halide_profiler_pipeline_stats *p = s->pipelines; p; p = (halide_profiler_pipeline_stats *)(p->next)) {
        print(NULL) << p->name << " : " << p->first_func_id << ", " << p->num_funcs << "\n";
    }
    error(NULL) << "Could not proceed.\n";
}

// TODO: make this something like halide_nanosleep so that it can be implemented per OS
extern "C" void usleep(int);

WEAK void *sampling_profiler_thread(void *) {
    halide_profiler_state *s = halide_profiler_get_state();

    // grab the lock
    halide_mutex_lock(&s->lock);

    while (s->current_func != halide_profiler_please_stop) {

        uint64_t t1 = halide_current_time_ns(NULL);
        uint64_t t = t1;
        while (1) {
            uint64_t t_now = halide_current_time_ns(NULL);
            int func = s->current_func;
            if (func == halide_profiler_please_stop) {
                break;
            } else if (func >= 0) {
               // Assume all time since I was last awake is due to
               // the currently running func.
               bill_func(s, func, t_now - t);
            }
            t = t_now;

            // Release the lock, sleep, reacquire.
            uint64_t sleep_ns = s->sleep_time;
            halide_mutex_unlock(&s->lock);
            usleep(sleep_ns/1000);
            halide_mutex_lock(&s->lock);
        }
    }

    s->started = false;

    halide_mutex_unlock(&s->lock);
    return NULL;
}

}}}

extern "C" {

// Returns a token identifying this pipeline instance.
WEAK int halide_profiler_pipeline_start(void *user_context,
                                        const char *pipeline_name,
                                        int num_funcs,
                                        const char **func_names) {
    halide_profiler_state *s = halide_profiler_get_state();

    ScopedMutexLock lock(&s->lock);

    if (!s->started) {
        halide_spawn_thread(user_context, sampling_profiler_thread, NULL);
        s->started = true;
    }

    halide_profiler_pipeline_stats *p =
        find_or_create_pipeline(pipeline_name, num_funcs, func_names);
    if (!p) {
        // Allocating space to track the statistics failed.
        return halide_error_out_of_memory(user_context);
    }
    p->runs++;

    return p->first_func_id;
}

WEAK void halide_profiler_report_unlocked(void *user_context, halide_profiler_state *s) {

    char line_buf[160];
    Printer<StringStreamPrinter, sizeof(line_buf)> sstr(user_context, line_buf);

    for (halide_profiler_pipeline_stats *p = s->pipelines; p;
         p = (halide_profiler_pipeline_stats *)(p->next)) {
        float t = p->time / 1000000.0f;
        if (!p->runs) continue;
        sstr.clear();
        sstr << p->name
             << "  total time: " << t << " ms"
             << "  samples: " << p->samples
             << "  runs: " << p->runs
             << "  time per run: " << t / p->runs << " ms\n";
        halide_print(user_context, sstr.str());
        if (p->time) {
            for (int i = 0; i < p->num_funcs; i++) {
                sstr.clear();
                halide_profiler_func_stats *fs = p->funcs + i;

                // The first func is always a catch-all overhead
                // slot. Only report overhead time if it's non-zero
                if (i == 0 && fs->time == 0) continue;

                sstr << "  " << fs->name << ": ";
                while (sstr.size() < 25) sstr << " ";

                float ft = fs->time / (p->runs * 1000000.0f);
                sstr << ft << "ms";
                while (sstr.size() < 40) sstr << " ";

                int percent = fs->time / (p->time / 100);
                sstr << "(" << percent << "%)\n";

                halide_print(user_context, sstr.str());
            }
        }
    }
}

WEAK void halide_profiler_report(void *user_context) {
    halide_profiler_state *s = halide_profiler_get_state();
    ScopedMutexLock lock(&s->lock);
    halide_profiler_report_unlocked(user_context, s);
}

WEAK void halide_profiler_reset() {
    halide_profiler_state *s = halide_profiler_get_state();

    ScopedMutexLock lock(&s->lock);

    while (s->pipelines) {
        halide_profiler_pipeline_stats *p = s->pipelines;
        s->pipelines = (halide_profiler_pipeline_stats *)(p->next);
        halide_free(NULL, p->funcs);
        halide_free(NULL, p);
    }
    s->first_free_id = 0;
}

namespace {
__attribute__((destructor))
WEAK void halide_profiler_shutdown() {
    halide_profiler_state *s = halide_profiler_get_state();
    s->current_func = halide_profiler_please_stop;
    do {
        // Memory barrier.
        __sync_synchronize(&s->started,
                           &s->current_func);
    } while (s->started);
    s->current_func = halide_profiler_outside_of_halide;

    // Print results. No need to lock anything because we just shut
    // down the thread.
    halide_profiler_report_unlocked(NULL, s);

    // Leak the memory. Not all implementations of halide_free may be
    // safe at static destruction time, and if there are multiple
    // copies of the runtime in the process this shutdown might get
    // called multiple times on the same state (Not sure why this is
    // possible, but I have seen it happen).
    // halide_profiler_reset();
}
}

WEAK void halide_profiler_pipeline_end(void *user_context, void *state) {
    ((halide_profiler_state *)state)->current_func = halide_profiler_outside_of_halide;
}

}
<|endoftext|>


<commit_before>#include "runtime_internal.h"
#include "HalideRuntimeQurt.h"
#include "printer.h"
#include "qurt.h"

using namespace Halide::Runtime::Internal::Qurt;

extern "C" {

enum qurt_hvx_mode_t {
    QURT_HVX_MODE_64B = 0,
    QURT_HVX_MODE_128B = 1,
};

extern int qurt_hvx_lock(qurt_hvx_mode_t);
extern int qurt_hvx_unlock();

WEAK int halide_qurt_hvx_lock(void *user_context, int size) {
    qurt_hvx_mode_t mode;
    switch (size) {
    case 64: mode = QURT_HVX_MODE_64B; break;
    case 128: mode = QURT_HVX_MODE_128B; break;
    default:
        error(user_context) << "HVX lock size must be 64 or 128.\n";
        return -1;
    }

    debug(user_context) << "QuRT: qurt_hvx_lock(" << mode << ") ->\n";
    int result = qurt_hvx_lock(mode);
    debug(user_context) << "        " << result;
    if (result != QURT_EOK) {
        error(user_context) << "qurt_hvx_lock failed\n";
        return -1;
    }

    return 0;
}

WEAK int halide_qurt_hvx_unlock(void *user_context) {
    debug(user_context) << "QuRT: qurt_hvx_unlock ->\n";
    int result = qurt_hvx_unlock();
    debug(user_context) << "        " << result;
    if (result != QURT_EOK) {
        error(user_context) << "qurt_hvx_unlock failed\n";
        return -1;
    }

    return 0;
}

WEAK void halide_qurt_hvx_unlock_as_destructor(void *user_context, void * /*obj*/) {
    halide_qurt_hvx_unlock(user_context);
}

}
<commit_msg>Fix badly formatted output.<commit_after>#include "runtime_internal.h"
#include "HalideRuntimeQurt.h"
#include "printer.h"
#include "qurt.h"

using namespace Halide::Runtime::Internal::Qurt;

extern "C" {

enum qurt_hvx_mode_t {
    QURT_HVX_MODE_64B = 0,
    QURT_HVX_MODE_128B = 1,
};

extern int qurt_hvx_lock(qurt_hvx_mode_t);
extern int qurt_hvx_unlock();

WEAK int halide_qurt_hvx_lock(void *user_context, int size) {
    qurt_hvx_mode_t mode;
    switch (size) {
    case 64: mode = QURT_HVX_MODE_64B; break;
    case 128: mode = QURT_HVX_MODE_128B; break;
    default:
        error(user_context) << "HVX lock size must be 64 or 128.\n";
        return -1;
    }

    debug(user_context) << "QuRT: qurt_hvx_lock(" << mode << ") ->\n";
    int result = qurt_hvx_lock(mode);
    debug(user_context) << "        " << result << "\n";
    if (result != QURT_EOK) {
        error(user_context) << "qurt_hvx_lock failed\n";
        return -1;
    }

    return 0;
}

WEAK int halide_qurt_hvx_unlock(void *user_context) {
    debug(user_context) << "QuRT: qurt_hvx_unlock ->\n";
    int result = qurt_hvx_unlock();
    debug(user_context) << "        " << result << "\n";
    if (result != QURT_EOK) {
        error(user_context) << "qurt_hvx_unlock failed\n";
        return -1;
    }

    return 0;
}

WEAK void halide_qurt_hvx_unlock_as_destructor(void *user_context, void * /*obj*/) {
    halide_qurt_hvx_unlock(user_context);
}

}
<|endoftext|>


<commit_before>#include "blackmagicsdk_video_source.h"

namespace gg
{

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK()
    : IVideoSource()
    , _frame_rate(0.0)
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    , _cols(0)
    , _rows(0)
    // This constructor should never be called,
    // therefore setting I420 arbitrarily for the
    // buffer video frame here.
    , _buffer_video_frame(VideoFrame(I420))
    , _running(false)
{
    // nop
}

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK(size_t deck_link_index,
                                                   ColourSpace colour)
    : IVideoSource(colour)
    , _frame_rate(0.0)
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    , _cols(0)
    , _rows(0)
    , _buffer_video_frame(VideoFrame(colour, false)) // TODO manage data?
    , _deck_link(nullptr)
    , _deck_link_input(nullptr)
    , _running(false)
{
    switch(_colour)
    {
    case BGRA:
        break;
    case I420:
    default:
        release_deck_link();
        throw VideoSourceError(
            "BlackmagicSDK video source supports only BGRA"
        );
    }

    // Get an iterator through the available DeckLink ports
    IDeckLinkIterator * deck_link_iterator = CreateDeckLinkIteratorInstance();
    if (deck_link_iterator == nullptr)
    {
        release_deck_link();
        throw VideoSourceError("DeckLink drivers do not appear to be installed");
    }

    HRESULT res;

    // Get the desired DeckLink index (port)
    int idx = deck_link_index;
    while ((res = deck_link_iterator->Next(&_deck_link)) == S_OK)
    {
        if (idx == 0)
            break;
        --idx;

        _deck_link->Release();
    }
    if (deck_link_iterator != nullptr)
        deck_link_iterator->Release();
    // No glory: release everything and throw exception
    if (res != S_OK or _deck_link == nullptr)
    {
        release_deck_link();
        throw VideoSourceError(
            std::string("Could not get DeckLink device ").append(std::to_string(deck_link_index))
        );
    }

    // Get the input interface of connected DeckLink port
    res = _deck_link->QueryInterface(IID_IDeckLinkInput, reinterpret_cast<void **>(&_deck_link_input));
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not get the Blackmagic DeckLink input interface");
    }

    // Set this object (IDeckLinkInputCallback instance) as callback
    res = _deck_link_input->SetCallback(this);
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not set the callback of Blackmagic DeckLink device");
    }

    // Try to set the first available of the following modes (in descending frame-rate order)
    std::vector<BMDDisplayMode> display_modes =
        { bmdModeHD1080p6000, bmdModeHD1080p5994, bmdModeHD1080p50,
          bmdModeHD1080p30, bmdModeHD1080p2997, bmdModeHD1080p25,
          bmdModeHD1080p24, bmdModeHD1080p2398 };
    // and BGRA as pixel format
    BMDPixelFormat pixel_format = bmdFormat8BitBGRA;
    // and these video flags
    BMDVideoInputFlags video_input_flags = bmdVideoInputFlagDefault | bmdVideoInputEnableFormatDetection;
    // These two are output variables
    BMDDisplayModeSupport display_mode_support;
    IDeckLinkDisplayMode * deck_link_display_mode = nullptr;
    // Flag for indicating the result of the video input enable attempt
    bool enabled_video_input = false;
    // And an error string to be set according to any failing intermediate step
    std::string error_msg = "";

    // Now loop through the set of modes
    for (BMDDisplayMode display_mode : display_modes)
    {
        // Check whether the mode is supported
        res = _deck_link_input->DoesSupportVideoMode(
            display_mode, pixel_format, video_input_flags,
            &display_mode_support, &deck_link_display_mode
        );
        // No glory (could not even check mode support)
        if (res != S_OK or deck_link_display_mode == nullptr)
        {
            error_msg = "Could not check video mode support of Blackmagic DeckLink device";
            break;
        }

        // If mode supported, set it and exit loop
        if (display_mode_support == bmdDisplayModeSupported)
        {
            // Get frame rate of DeckLink device
            BMDTimeValue frame_rate_duration, frame_rate_scale;
            res = deck_link_display_mode->GetFrameRate(&frame_rate_duration, &frame_rate_scale);
            // No glory
            if (res != S_OK)
            {
                error_msg = "Could not infer frame rate of Blackmagic DeckLink device";
                break;
            }
            _frame_rate = (double) frame_rate_scale / (double) frame_rate_duration;

            // Enable video input
            res = _deck_link_input->EnableVideoInput(display_mode,
                                                     pixel_format,
                                                     video_input_flags);
            // No glory
            if (res != S_OK)
            {
                error_msg = "Could not enable video input of Blackmagic DeckLink device";
                break;
            }

            enabled_video_input = true;
        }

        // Release the DeckLink display mode object at each iteration
        if (deck_link_display_mode != nullptr)
        {
            deck_link_display_mode->Release();
            deck_link_display_mode = nullptr;
        }

        if (enabled_video_input)
            break;
    }

    // Release the DeckLink display mode object in case loop pre-maturely broken
    if (deck_link_display_mode != nullptr)
        deck_link_display_mode->Release();

    // No glory (loop exited without success): release everything and throw exception
    if (not enabled_video_input)
    {
        release_deck_link();
        // If all modes checked, and none is supported!
        if (error_msg.empty())
            error_msg = "Your Blackmagic DeckLink device does not "
                        "seem to support a 1080p mode";
        // Else: an intermediate step went wrong, so put that into the exception
        throw VideoSourceError(error_msg);
    }

    // Start streaming
    _running = true;
    res = _deck_link_input->StartStreams();
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        _running = false;
        release_deck_link();
        throw VideoSourceError("Could not start streaming from the Blackmagic DeckLink device");
    }
}

VideoSourceBlackmagicSDK::~VideoSourceBlackmagicSDK()
{
    // Make sure streamer thread not trying to access buffer
    std::lock_guard<std::mutex> data_lock_guard(_data_lock);
    _running = false;

    // Stop streaming and disable enabled inputs
    _deck_link_input->StopStreams();
    _deck_link_input->DisableVideoInput();

    // Release DeckLink members
    release_deck_link();
}

bool VideoSourceBlackmagicSDK::get_frame_dimensions(int & width, int & height)
{
    // Make sure only this thread is accessing the cols and rows members now
    std::lock_guard<std::mutex> data_lock_guard(_data_lock);
    if (_cols <= 0 or _rows <= 0)
        return false;

    width = _cols;
    height = _rows;
    return true;
}

bool VideoSourceBlackmagicSDK::get_frame(VideoFrame & frame)
{
    // Make sure only this thread is accessing the video frame data now
    std::lock_guard<std::mutex> data_lock_guard(_data_lock);

    if (_video_buffer_length > 0 and _cols > 0 and _rows > 0)
    {
        frame.init_from_specs(_video_buffer, _video_buffer_length, _cols, _rows);
        return true;
    }
    else
        return false;
}

double VideoSourceBlackmagicSDK::get_frame_rate()
{
    return _frame_rate;
}

void VideoSourceBlackmagicSDK::set_sub_frame(int x, int y, int width, int height)
{
    // TODO
}

void VideoSourceBlackmagicSDK::get_full_frame()
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::QueryInterface(REFIID iid, LPVOID * ppv)
{
    return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::AddRef(void)
{
    return __sync_add_and_fetch(&_n_ref, 1);
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::Release(void)
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFormatChanged(
    BMDVideoInputFormatChangedEvents events,
    IDeckLinkDisplayMode * display_mode,
    BMDDetectedVideoInputFormatFlags format_flags
)
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFrameArrived(
    IDeckLinkVideoInputFrame * video_frame,
    IDeckLinkAudioInputPacket * audio_packet
)
{
    // TODO
}

void VideoSourceBlackmagicSDK::release_deck_link() noexcept
{
    this->Release();

    if (_deck_link_input != nullptr)
    {
        _deck_link_input->Release();
        _deck_link_input = nullptr;
    }

    if (_deck_link != nullptr)
        _deck_link->Release();
}

}
<commit_msg>Issue #5: implemented the Release method of BlackmagicSDK video source inherited from IDeckLinkInputCallback<commit_after>#include "blackmagicsdk_video_source.h"

namespace gg
{

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK()
    : IVideoSource()
    , _frame_rate(0.0)
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    , _cols(0)
    , _rows(0)
    // This constructor should never be called,
    // therefore setting I420 arbitrarily for the
    // buffer video frame here.
    , _buffer_video_frame(VideoFrame(I420))
    , _running(false)
{
    // nop
}

VideoSourceBlackmagicSDK::VideoSourceBlackmagicSDK(size_t deck_link_index,
                                                   ColourSpace colour)
    : IVideoSource(colour)
    , _frame_rate(0.0)
    , _video_buffer(nullptr)
    , _video_buffer_length(0)
    , _cols(0)
    , _rows(0)
    , _buffer_video_frame(VideoFrame(colour, false)) // TODO manage data?
    , _deck_link(nullptr)
    , _deck_link_input(nullptr)
    , _running(false)
{
    switch(_colour)
    {
    case BGRA:
        break;
    case I420:
    default:
        release_deck_link();
        throw VideoSourceError(
            "BlackmagicSDK video source supports only BGRA"
        );
    }

    // Get an iterator through the available DeckLink ports
    IDeckLinkIterator * deck_link_iterator = CreateDeckLinkIteratorInstance();
    if (deck_link_iterator == nullptr)
    {
        release_deck_link();
        throw VideoSourceError("DeckLink drivers do not appear to be installed");
    }

    HRESULT res;

    // Get the desired DeckLink index (port)
    int idx = deck_link_index;
    while ((res = deck_link_iterator->Next(&_deck_link)) == S_OK)
    {
        if (idx == 0)
            break;
        --idx;

        _deck_link->Release();
    }
    if (deck_link_iterator != nullptr)
        deck_link_iterator->Release();
    // No glory: release everything and throw exception
    if (res != S_OK or _deck_link == nullptr)
    {
        release_deck_link();
        throw VideoSourceError(
            std::string("Could not get DeckLink device ").append(std::to_string(deck_link_index))
        );
    }

    // Get the input interface of connected DeckLink port
    res = _deck_link->QueryInterface(IID_IDeckLinkInput, reinterpret_cast<void **>(&_deck_link_input));
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not get the Blackmagic DeckLink input interface");
    }

    // Set this object (IDeckLinkInputCallback instance) as callback
    res = _deck_link_input->SetCallback(this);
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        release_deck_link();
        throw VideoSourceError("Could not set the callback of Blackmagic DeckLink device");
    }

    // Try to set the first available of the following modes (in descending frame-rate order)
    std::vector<BMDDisplayMode> display_modes =
        { bmdModeHD1080p6000, bmdModeHD1080p5994, bmdModeHD1080p50,
          bmdModeHD1080p30, bmdModeHD1080p2997, bmdModeHD1080p25,
          bmdModeHD1080p24, bmdModeHD1080p2398 };
    // and BGRA as pixel format
    BMDPixelFormat pixel_format = bmdFormat8BitBGRA;
    // and these video flags
    BMDVideoInputFlags video_input_flags = bmdVideoInputFlagDefault | bmdVideoInputEnableFormatDetection;
    // These two are output variables
    BMDDisplayModeSupport display_mode_support;
    IDeckLinkDisplayMode * deck_link_display_mode = nullptr;
    // Flag for indicating the result of the video input enable attempt
    bool enabled_video_input = false;
    // And an error string to be set according to any failing intermediate step
    std::string error_msg = "";

    // Now loop through the set of modes
    for (BMDDisplayMode display_mode : display_modes)
    {
        // Check whether the mode is supported
        res = _deck_link_input->DoesSupportVideoMode(
            display_mode, pixel_format, video_input_flags,
            &display_mode_support, &deck_link_display_mode
        );
        // No glory (could not even check mode support)
        if (res != S_OK or deck_link_display_mode == nullptr)
        {
            error_msg = "Could not check video mode support of Blackmagic DeckLink device";
            break;
        }

        // If mode supported, set it and exit loop
        if (display_mode_support == bmdDisplayModeSupported)
        {
            // Get frame rate of DeckLink device
            BMDTimeValue frame_rate_duration, frame_rate_scale;
            res = deck_link_display_mode->GetFrameRate(&frame_rate_duration, &frame_rate_scale);
            // No glory
            if (res != S_OK)
            {
                error_msg = "Could not infer frame rate of Blackmagic DeckLink device";
                break;
            }
            _frame_rate = (double) frame_rate_scale / (double) frame_rate_duration;

            // Enable video input
            res = _deck_link_input->EnableVideoInput(display_mode,
                                                     pixel_format,
                                                     video_input_flags);
            // No glory
            if (res != S_OK)
            {
                error_msg = "Could not enable video input of Blackmagic DeckLink device";
                break;
            }

            enabled_video_input = true;
        }

        // Release the DeckLink display mode object at each iteration
        if (deck_link_display_mode != nullptr)
        {
            deck_link_display_mode->Release();
            deck_link_display_mode = nullptr;
        }

        if (enabled_video_input)
            break;
    }

    // Release the DeckLink display mode object in case loop pre-maturely broken
    if (deck_link_display_mode != nullptr)
        deck_link_display_mode->Release();

    // No glory (loop exited without success): release everything and throw exception
    if (not enabled_video_input)
    {
        release_deck_link();
        // If all modes checked, and none is supported!
        if (error_msg.empty())
            error_msg = "Your Blackmagic DeckLink device does not "
                        "seem to support a 1080p mode";
        // Else: an intermediate step went wrong, so put that into the exception
        throw VideoSourceError(error_msg);
    }

    // Start streaming
    _running = true;
    res = _deck_link_input->StartStreams();
    // No glory: release everything and throw exception
    if (res != S_OK)
    {
        _running = false;
        release_deck_link();
        throw VideoSourceError("Could not start streaming from the Blackmagic DeckLink device");
    }
}

VideoSourceBlackmagicSDK::~VideoSourceBlackmagicSDK()
{
    // Make sure streamer thread not trying to access buffer
    std::lock_guard<std::mutex> data_lock_guard(_data_lock);
    _running = false;

    // Stop streaming and disable enabled inputs
    _deck_link_input->StopStreams();
    _deck_link_input->DisableVideoInput();

    // Release DeckLink members
    release_deck_link();
}

bool VideoSourceBlackmagicSDK::get_frame_dimensions(int & width, int & height)
{
    // Make sure only this thread is accessing the cols and rows members now
    std::lock_guard<std::mutex> data_lock_guard(_data_lock);
    if (_cols <= 0 or _rows <= 0)
        return false;

    width = _cols;
    height = _rows;
    return true;
}

bool VideoSourceBlackmagicSDK::get_frame(VideoFrame & frame)
{
    // Make sure only this thread is accessing the video frame data now
    std::lock_guard<std::mutex> data_lock_guard(_data_lock);

    if (_video_buffer_length > 0 and _cols > 0 and _rows > 0)
    {
        frame.init_from_specs(_video_buffer, _video_buffer_length, _cols, _rows);
        return true;
    }
    else
        return false;
}

double VideoSourceBlackmagicSDK::get_frame_rate()
{
    return _frame_rate;
}

void VideoSourceBlackmagicSDK::set_sub_frame(int x, int y, int width, int height)
{
    // TODO
}

void VideoSourceBlackmagicSDK::get_full_frame()
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::QueryInterface(REFIID iid, LPVOID * ppv)
{
    return E_NOINTERFACE;
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::AddRef(void)
{
    return __sync_add_and_fetch(&_n_ref, 1);
}

ULONG STDMETHODCALLTYPE VideoSourceBlackmagicSDK::Release(void)
{
    int32_t new_n_ref = __sync_sub_and_fetch(&_n_ref, 1);
    if (new_n_ref == 0)
        delete this;
    return new_n_ref;
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFormatChanged(
    BMDVideoInputFormatChangedEvents events,
    IDeckLinkDisplayMode * display_mode,
    BMDDetectedVideoInputFormatFlags format_flags
)
{
    // TODO
}

HRESULT STDMETHODCALLTYPE VideoSourceBlackmagicSDK::VideoInputFrameArrived(
    IDeckLinkVideoInputFrame * video_frame,
    IDeckLinkAudioInputPacket * audio_packet
)
{
    // TODO
}

void VideoSourceBlackmagicSDK::release_deck_link() noexcept
{
    if (_deck_link_input != nullptr)
    {
        _deck_link_input->Release();
        _deck_link_input = nullptr;
    }

    if (_deck_link != nullptr)
        _deck_link->Release();
}

}
<|endoftext|>


<commit_before>#include "common.hpp"
#include "avecado.hpp"

#include <iostream>

#include <mapnik/utils.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/json/feature_generator.hpp>
#include <mapnik/json/feature_generator_grammar_impl.hpp>
#include <mapnik/json/geometry_generator_grammar_impl.hpp>

#include "vector_tile.pb.h"
#include "vector_tile_datasource.hpp"

#include "config.h"

using std::cout;
using std::endl;

#define WORLD_SIZE (40075016.68)

mapnik::box2d<double> box_for_tile(int z, int x, int y) {
  const double scale = WORLD_SIZE / double(1 << z);
  const double half_world = 0.5 * WORLD_SIZE;

  return mapnik::box2d<double>(
    x * scale - half_world,
    half_world - (y+1) * scale,
    (x+1) * scale - half_world,
    half_world - y * scale);
}

// Default constants

const unsigned int path_multiplier = 1;
const int buffer_size = 0;
const double scale_factor = 1.0;
const unsigned int offset_x = 0;
const unsigned int offset_y = 0;
const unsigned int tolerance = 1;
const std::string image_format = "jpeg";
const mapnik::scaling_method_e scaling_method = mapnik::SCALING_NEAR;
const double scale_denominator = 0;

const unsigned tile_size = 256;
const unsigned _x=0,_y=0,_z=0;
const mapnik::box2d<double> bbox = box_for_tile(_z, _x, _y);

void setup_mapnik() {
  mapnik::freetype_engine::register_fonts(MAPNIK_DEFAULT_FONT_DIR);
  mapnik::datasource_cache::instance().register_datasources(MAPNIK_DEFAULT_INPUT_PLUGIN_DIR);
}

/* See bindings/python/mapnik_feature.cpp from Mapnik */
std::string feature_to_geojson(mapnik::feature_impl const& feature)
{
  std::string json;
  test::assert_equal(mapnik::json::to_geojson(json,feature), true, "Failed to convert to GeoJSON");
  return json;
}

/* JSON strings for map layers. These have a loss of precisision from the
 * vector tile conversion, and the best way to generate them is just to take
 * the actual output and then check that it's sensible */
const std::string single_point_json (R"({"type":"Feature","id":1,"geometry":{"type":"Point","coordinates":[0,0]},"properties":{"name":"null island"}})");
const std::string single_line_json (R"({"type":"Feature","id":1,"geometry":{"type":"LineString","coordinates":[[-2035059.44106453,0],[-939258.203568246,1252344.27142433],[939258.203568246,939258.203568246],[2035059.44106453,-0.0000000001164153]]},"properties":{"name":"null highway"}})");
const std::string single_poly_json (R"({"type":"Feature","id":1,"geometry":{"type":"Polygon","coordinates":[[[-2035059.44106453,0],[-939258.203568246,1095801.23749629],[939258.203568246,939258.203568246],[2035059.44106453,0],[-2035059.44106453,0],[-2035059.44106453,0]],[[-156543.033928041,0],[0.0000000000873115,156543.033928041],[156543.033928041,0],[-156543.033928041,0],[-156543.033928041,0]]]},"properties":{"name":"null lake"}})");
// intersected with a z1 tile
const std::string single_line_z1_json (R"({"type":"Feature","id":1,"geometry":{"type":"LineString","coordinates":[[-2035059.44106453,0],[-1017529.72053227,1252344.27142433],[-0.0000000002328306,1095801.23749629]]},"properties":{"name":"null highway"}})");

void test_single_point() {
/* This test uses a map file with a CSV source single point at 0,0 and checks
 * the resulting vector tile at 0/0/0
 */
  mapnik::Map map;
  avecado::tile tile;
  mapnik::load_map(map, "test/single_point.xml");
  map.resize(tile_size, tile_size);
  map.zoom_to_box(bbox);
  avecado::make_vector_tile(tile, path_multiplier, map, buffer_size, scale_factor,
                            offset_x, offset_y, tolerance, image_format,
                            scaling_method, scale_denominator, boost::none);
  mapnik::vector::tile result;
  result.ParseFromString(tile.get_data());
  test::assert_equal(result.layers_size(), 1, "Wrong number of layers");
  mapnik::vector::tile_layer layer = result.layers(0);

  // Query the layer with mapnik. See https://github.com/mapbox/mapnik-vector-tile/blob/2e3e2c28/test/vector_tile.cpp#L236
  mapnik::vector::tile_datasource ds(layer, 0, 0, 0, tile_size);

  mapnik::query qq = mapnik::query(bbox);
  qq.add_property_name("name");
  mapnik::featureset_ptr fs;
  fs = ds.features(qq);
  mapnik::feature_ptr feat = fs->next();
  std::string json = feature_to_geojson(*feat);
  test::assert_equal(json, single_point_json, "Wrong JSON");
}

void test_single_line() {
/* This test uses a map file with a CSV source line and checks the resulting
 * vector tile at 0/0/0
 */
  mapnik::Map map;
  avecado::tile tile;
  mapnik::load_map(map, "test/single_line.xml");
  map.resize(tile_size, tile_size);
  map.zoom_to_box(bbox);
  avecado::make_vector_tile(tile, path_multiplier, map, buffer_size, scale_factor,
                            offset_x, offset_y, tolerance, image_format,
                            scaling_method, scale_denominator);
  mapnik::vector::tile result;
  result.ParseFromString(tile.get_data());
  test::assert_equal(result.layers_size(), 1, "Wrong number of layers");
  mapnik::vector::tile_layer layer = result.layers(0);

  // Query the layer with mapnik. See https://github.com/mapbox/mapnik-vector-tile/blob/2e3e2c28/test/vector_tile.cpp#L236
  mapnik::vector::tile_datasource ds(layer, 0, 0, 0, tile_size);

  mapnik::query qq = mapnik::query(bbox);
  qq.add_property_name("name");
  mapnik::featureset_ptr fs;
  fs = ds.features(qq);
  mapnik::feature_ptr feat = fs->next();
  std::string json = feature_to_geojson(*feat);
  test::assert_equal(json, single_line_json, "Wrong JSON");
}

void test_single_polygon() {
/* This test uses a map file with a CSV source polygon and checks the
 * resulting vector tile at 0/0/0
 */
  mapnik::Map map;
  avecado::tile tile;
  mapnik::load_map(map, "test/single_poly.xml");
  map.resize(tile_size, tile_size);
  map.zoom_to_box(bbox);
  avecado::make_vector_tile(tile, path_multiplier, map, buffer_size, scale_factor,
                            offset_x, offset_y, tolerance, image_format,
                            scaling_method, scale_denominator);
  mapnik::vector::tile result;
  result.ParseFromString(tile.get_data());
  test::assert_equal(result.layers_size(), 1, "Wrong number of layers");
  mapnik::vector::tile_layer layer = result.layers(0);

  // Query the layer with mapnik. See https://github.com/mapbox/mapnik-vector-tile/blob/2e3e2c28/test/vector_tile.cpp#L236
  mapnik::vector::tile_datasource ds(layer, 0, 0, 0, tile_size);

  mapnik::query qq = mapnik::query(bbox);
  qq.add_property_name("name");
  mapnik::featureset_ptr fs;
  fs = ds.features(qq);
  mapnik::feature_ptr feat = fs->next();
  std::string json = feature_to_geojson(*feat);
  test::assert_equal(json, single_poly_json, "Wrong JSON");
}

void test_intersected_line() {
/* This test uses a map file with a CSV source line and checks the resulting
 * vector tile for 1/0/0, while the line extends outside that tile
 */
  mapnik::Map map;
  avecado::tile tile;
  mapnik::load_map(map, "test/single_line.xml");
  map.resize(tile_size, tile_size);
  map.zoom_to_box(box_for_tile(1, 0, 0));
  avecado::make_vector_tile(tile, path_multiplier, map, buffer_size, scale_factor,
                            offset_x, offset_y, tolerance, image_format,
                            scaling_method, scale_denominator);
  mapnik::vector::tile result;
  result.ParseFromString(tile.get_data());
  test::assert_equal(result.layers_size(), 1, "Wrong number of layers");
  mapnik::vector::tile_layer layer = result.layers(0);

  // Query the layer with mapnik. See https://github.com/mapbox/mapnik-vector-tile/blob/2e3e2c28/test/vector_tile.cpp#L236
  // note tile_datasource has x, y, z
  mapnik::vector::tile_datasource ds(layer, 0, 0, 1, tile_size);

  mapnik::query qq = mapnik::query(box_for_tile(1, 0, 0));
  qq.add_property_name("name");
  mapnik::featureset_ptr fs;
  fs = ds.features(qq);
  mapnik::feature_ptr feat = fs->next();
  std::string json = feature_to_geojson(*feat);
  test::assert_equal(json, single_line_z1_json, "Wrong JSON");
}

int main() {
  int tests_failed = 0;

  cout << "== Testing make_vector_tile ==" << endl << endl;

#define RUN_TEST(x) { tests_failed += test::run(#x, &(x)); }
  RUN_TEST(setup_mapnik);
  RUN_TEST(test_single_point);
  RUN_TEST(test_single_line);
  RUN_TEST(test_single_polygon);
  RUN_TEST(test_intersected_line);
  cout << " >> Tests failed: " << tests_failed << endl << endl;

  return (tests_failed > 0) ? 1 : 0;

}
<commit_msg>Fix tests broken in merge.<commit_after>#include "common.hpp"
#include "avecado.hpp"

#include <iostream>

#include <mapnik/utils.hpp>
#include <mapnik/load_map.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/json/feature_generator.hpp>
#include <mapnik/json/feature_generator_grammar_impl.hpp>
#include <mapnik/json/geometry_generator_grammar_impl.hpp>

#include "vector_tile.pb.h"
#include "vector_tile_datasource.hpp"

#include "config.h"

using std::cout;
using std::endl;

#define WORLD_SIZE (40075016.68)

mapnik::box2d<double> box_for_tile(int z, int x, int y) {
  const double scale = WORLD_SIZE / double(1 << z);
  const double half_world = 0.5 * WORLD_SIZE;

  return mapnik::box2d<double>(
    x * scale - half_world,
    half_world - (y+1) * scale,
    (x+1) * scale - half_world,
    half_world - y * scale);
}

// Default constants

const unsigned int path_multiplier = 1;
const int buffer_size = 0;
const double scale_factor = 1.0;
const unsigned int offset_x = 0;
const unsigned int offset_y = 0;
const unsigned int tolerance = 1;
const std::string image_format = "jpeg";
const mapnik::scaling_method_e scaling_method = mapnik::SCALING_NEAR;
const double scale_denominator = 0;

const unsigned tile_size = 256;
const unsigned _x=0,_y=0,_z=0;
const mapnik::box2d<double> bbox = box_for_tile(_z, _x, _y);

void setup_mapnik() {
  mapnik::freetype_engine::register_fonts(MAPNIK_DEFAULT_FONT_DIR);
  mapnik::datasource_cache::instance().register_datasources(MAPNIK_DEFAULT_INPUT_PLUGIN_DIR);
}

/* See bindings/python/mapnik_feature.cpp from Mapnik */
std::string feature_to_geojson(mapnik::feature_impl const& feature)
{
  std::string json;
  test::assert_equal(mapnik::json::to_geojson(json,feature), true, "Failed to convert to GeoJSON");
  return json;
}

/* JSON strings for map layers. These have a loss of precisision from the
 * vector tile conversion, and the best way to generate them is just to take
 * the actual output and then check that it's sensible */
const std::string single_point_json (R"({"type":"Feature","id":1,"geometry":{"type":"Point","coordinates":[0,0]},"properties":{"name":"null island"}})");
const std::string single_line_json (R"({"type":"Feature","id":1,"geometry":{"type":"LineString","coordinates":[[-2035059.44106453,0],[-939258.203568246,1252344.27142433],[939258.203568246,939258.203568246],[2035059.44106453,-0.0000000001164153]]},"properties":{"name":"null highway"}})");
const std::string single_poly_json (R"({"type":"Feature","id":1,"geometry":{"type":"Polygon","coordinates":[[[-2035059.44106453,0],[-939258.203568246,1095801.23749629],[939258.203568246,939258.203568246],[2035059.44106453,0],[-2035059.44106453,0],[-2035059.44106453,0]],[[-156543.033928041,0],[0.0000000000873115,156543.033928041],[156543.033928041,0],[-156543.033928041,0],[-156543.033928041,0]]]},"properties":{"name":"null lake"}})");
// intersected with a z1 tile
const std::string single_line_z1_json (R"({"type":"Feature","id":1,"geometry":{"type":"LineString","coordinates":[[-2035059.44106453,0],[-1017529.72053227,1252344.27142433],[-0.0000000002328306,1095801.23749629]]},"properties":{"name":"null highway"}})");

void test_single_point() {
/* This test uses a map file with a CSV source single point at 0,0 and checks
 * the resulting vector tile at 0/0/0
 */
  mapnik::Map map;
  avecado::tile tile;
  mapnik::load_map(map, "test/single_point.xml");
  map.resize(tile_size, tile_size);
  map.zoom_to_box(bbox);
  avecado::make_vector_tile(tile, path_multiplier, map, buffer_size, scale_factor,
                            offset_x, offset_y, tolerance, image_format,
                            scaling_method, scale_denominator, boost::none);
  mapnik::vector::tile result;
  result.ParseFromString(tile.get_data());
  test::assert_equal(result.layers_size(), 1, "Wrong number of layers");
  mapnik::vector::tile_layer layer = result.layers(0);

  // Query the layer with mapnik. See https://github.com/mapbox/mapnik-vector-tile/blob/2e3e2c28/test/vector_tile.cpp#L236
  mapnik::vector::tile_datasource ds(layer, 0, 0, 0, tile_size);

  mapnik::query qq = mapnik::query(bbox);
  qq.add_property_name("name");
  mapnik::featureset_ptr fs;
  fs = ds.features(qq);
  mapnik::feature_ptr feat = fs->next();
  std::string json = feature_to_geojson(*feat);
  test::assert_equal(json, single_point_json, "Wrong JSON");
}

void test_single_line() {
/* This test uses a map file with a CSV source line and checks the resulting
 * vector tile at 0/0/0
 */
  mapnik::Map map;
  avecado::tile tile;
  mapnik::load_map(map, "test/single_line.xml");
  map.resize(tile_size, tile_size);
  map.zoom_to_box(bbox);
  avecado::make_vector_tile(tile, path_multiplier, map, buffer_size, scale_factor,
                            offset_x, offset_y, tolerance, image_format,
                            scaling_method, scale_denominator, boost::none);
  mapnik::vector::tile result;
  result.ParseFromString(tile.get_data());
  test::assert_equal(result.layers_size(), 1, "Wrong number of layers");
  mapnik::vector::tile_layer layer = result.layers(0);

  // Query the layer with mapnik. See https://github.com/mapbox/mapnik-vector-tile/blob/2e3e2c28/test/vector_tile.cpp#L236
  mapnik::vector::tile_datasource ds(layer, 0, 0, 0, tile_size);

  mapnik::query qq = mapnik::query(bbox);
  qq.add_property_name("name");
  mapnik::featureset_ptr fs;
  fs = ds.features(qq);
  mapnik::feature_ptr feat = fs->next();
  std::string json = feature_to_geojson(*feat);
  test::assert_equal(json, single_line_json, "Wrong JSON");
}

void test_single_polygon() {
/* This test uses a map file with a CSV source polygon and checks the
 * resulting vector tile at 0/0/0
 */
  mapnik::Map map;
  avecado::tile tile;
  mapnik::load_map(map, "test/single_poly.xml");
  map.resize(tile_size, tile_size);
  map.zoom_to_box(bbox);
  avecado::make_vector_tile(tile, path_multiplier, map, buffer_size, scale_factor,
                            offset_x, offset_y, tolerance, image_format,
                            scaling_method, scale_denominator, boost::none);
  mapnik::vector::tile result;
  result.ParseFromString(tile.get_data());
  test::assert_equal(result.layers_size(), 1, "Wrong number of layers");
  mapnik::vector::tile_layer layer = result.layers(0);

  // Query the layer with mapnik. See https://github.com/mapbox/mapnik-vector-tile/blob/2e3e2c28/test/vector_tile.cpp#L236
  mapnik::vector::tile_datasource ds(layer, 0, 0, 0, tile_size);

  mapnik::query qq = mapnik::query(bbox);
  qq.add_property_name("name");
  mapnik::featureset_ptr fs;
  fs = ds.features(qq);
  mapnik::feature_ptr feat = fs->next();
  std::string json = feature_to_geojson(*feat);
  test::assert_equal(json, single_poly_json, "Wrong JSON");
}

void test_intersected_line() {
/* This test uses a map file with a CSV source line and checks the resulting
 * vector tile for 1/0/0, while the line extends outside that tile
 */
  mapnik::Map map;
  avecado::tile tile;
  mapnik::load_map(map, "test/single_line.xml");
  map.resize(tile_size, tile_size);
  map.zoom_to_box(box_for_tile(1, 0, 0));
  avecado::make_vector_tile(tile, path_multiplier, map, buffer_size, scale_factor,
                            offset_x, offset_y, tolerance, image_format,
                            scaling_method, scale_denominator, boost::none);
  mapnik::vector::tile result;
  result.ParseFromString(tile.get_data());
  test::assert_equal(result.layers_size(), 1, "Wrong number of layers");
  mapnik::vector::tile_layer layer = result.layers(0);

  // Query the layer with mapnik. See https://github.com/mapbox/mapnik-vector-tile/blob/2e3e2c28/test/vector_tile.cpp#L236
  // note tile_datasource has x, y, z
  mapnik::vector::tile_datasource ds(layer, 0, 0, 1, tile_size);

  mapnik::query qq = mapnik::query(box_for_tile(1, 0, 0));
  qq.add_property_name("name");
  mapnik::featureset_ptr fs;
  fs = ds.features(qq);
  mapnik::feature_ptr feat = fs->next();
  std::string json = feature_to_geojson(*feat);
  test::assert_equal(json, single_line_z1_json, "Wrong JSON");
}

int main() {
  int tests_failed = 0;

  cout << "== Testing make_vector_tile ==" << endl << endl;

#define RUN_TEST(x) { tests_failed += test::run(#x, &(x)); }
  RUN_TEST(setup_mapnik);
  RUN_TEST(test_single_point);
  RUN_TEST(test_single_line);
  RUN_TEST(test_single_polygon);
  RUN_TEST(test_intersected_line);
  cout << " >> Tests failed: " << tests_failed << endl << endl;

  return (tests_failed > 0) ? 1 : 0;

}
<|endoftext|>


<commit_before>// (C) 2014 Arek Olek

#pragma once

#include <algorithm>
#include <functional>
#include <vector>

#include <boost/iterator/counting_iterator.hpp>

#include "range.hpp"

template <class Input, class Output>
void copy_edges(const Input& in, Output& out) {
  for(auto e : range(edges(in)))
    add_edge(source(e, in), target(e, in), out);
}

template<class Graph, class Generator>
void add_spider(Graph& G, unsigned legs, Generator generator) {
  unsigned n = num_vertices(G);
  unsigned cutoff = n / legs;
  auto range_iterator = boost::make_counting_iterator<int>;
  std::vector<int> path(range_iterator(0), range_iterator(n));
  std::shuffle(path.begin(), path.end(), generator);
  for(unsigned i = 0; i < n-1; ++i)
    add_edge(path[i % cutoff == 0 ? 0 : i], path[i+1], G);
}

template<class Graph, class Generator>
void add_edges_uniform(Graph& G, double p, Generator generator) {
  std::bernoulli_distribution distribution(p);
  auto trial = std::bind(distribution, generator);
  unsigned n = num_vertices(G);
  for(unsigned i = 0; i < n; ++i)
    for(unsigned j = i + 1; j < n; ++j)
      if(trial())
        add_edge(i, j, G);
}
<commit_msg>generate random geometric graphs<commit_after>// (C) 2014 Arek Olek

#pragma once

#include <algorithm>
#include <functional>
#include <utility>
#include <vector>

#include <boost/graph/adjacency_list.hpp>
#include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/function_input_iterator.hpp>
#include <boost/function_output_iterator.hpp>

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Point_set_2.h>

#include "range.hpp"

template <class Input, class Output>
void copy_edges(const Input& in, Output& out) {
  for(auto e : range(edges(in)))
    add_edge(source(e, in), target(e, in), out);
}

template<class Graph, class Generator>
void add_spider(Graph& G, unsigned legs, Generator generator) {
  unsigned n = num_vertices(G);
  unsigned cutoff = n / legs;
  auto range_iterator = boost::make_counting_iterator<int>;
  std::vector<int> path(range_iterator(0), range_iterator(n));
  std::shuffle(path.begin(), path.end(), generator);
  for(unsigned i = 0; i < n-1; ++i)
    add_edge(path[i % cutoff == 0 ? 0 : i], path[i+1], G);
}

template<class Graph, class Generator>
void add_edges_uniform(Graph& G, double p, Generator generator) {
  std::bernoulli_distribution distribution(p);
  auto trial = std::bind(distribution, generator);
  unsigned n = num_vertices(G);
  for(unsigned i = 0; i < n; ++i)
    for(unsigned j = i + 1; j < n; ++j)
      if(trial())
        add_edge(i, j, G);
}

template<class Graph, class Generator>
void add_random_geometric(Graph& G, double d, Generator generator) {
  CGAL::Exact_predicates_inexact_constructions_kernel           typedef Kernel;
  CGAL::Triangulation_vertex_base_with_info_2<unsigned, Kernel> typedef Vertex_struct;
  CGAL::Triangulation_data_structure_2<Vertex_struct>           typedef Triangulation_struct;
  CGAL::Point_set_2<Kernel, Triangulation_struct>               typedef Delaunay;
  CGAL::Circle_2<Kernel>                                        typedef Circle;
  Delaunay::Vertex_handle                                       typedef Vertex_handle;
  Delaunay::Point                                               typedef Point;

  // Choose random points in square [0, 1) x [0, 1)
  std::uniform_real_distribution<> distribution(0, 1);
  auto r = std::bind(distribution, generator);
  // Generate index for every point
  int n = boost::num_vertices(G), counter = 0;
  std::function<std::pair<Point, int>()> f =
    [&]() {return std::make_pair(Point(r(), r()), counter++); };
  // Initialize triangulation with n points
  Delaunay D(boost::make_function_input_iterator(f, 0),
             boost::make_function_input_iterator(f, n));
  // Query each point for other points lying in the circle
  for(auto v : range(D.finite_vertices_begin(), D.finite_vertices_end()))
    D.range_search(Circle(v.point(), d*d), boost::make_function_output_iterator(
        [&](Vertex_handle u){
          if(v.info() < u->info())
            boost::add_edge(v.info(), u->info(), G);
    }));
}
<|endoftext|>


<commit_before>// (C) 2014 Arek Olek

#pragma once

#include <algorithm>
#include <functional>
#include <utility>
#include <vector>

#include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/function_input_iterator.hpp>
#include <boost/function_output_iterator.hpp>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/connected_components.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
#include <boost/graph/boyer_myrvold_planar_test.hpp>
#include <boost/graph/planar_canonical_ordering.hpp>
#include <boost/graph/chrobak_payne_drawing.hpp>
#include <boost/graph/make_connected.hpp>
#include <boost/graph/make_biconnected_planar.hpp>
#include <boost/graph/make_maximal_planar.hpp>

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Point_set_2.h>
#include <CGAL/squared_distance_2.h>

#include "range.hpp"

template<class Graph>
unsigned num_internal(Graph const & G) {
  unsigned internal = 0;
  for (auto v : range(vertices(G)))
    internal += out_degree(v, G) > 1;
  return internal;
}

template<class Graph>
unsigned upper_bound(Graph const & G) {
  return std::min(num_internal(G), (unsigned) num_vertices(G) - 2);
}

template<class Graph>
bool is_connected(Graph const & G) {
  std::vector<int> component(num_vertices(G));
  return connected_components(G, &component[0]) == 1;
}

template<class G>
void add_edge_no_dup(
    typename boost::graph_traits<G>::vertex_descriptor v,
    typename boost::graph_traits<G>::vertex_descriptor u,
    G& g) {
  if(!edge(v, u, g).second) add_edge(v, u, g);
}

template <class Input, class Output>
void copy_edges(const Input& in, Output& out) {
  for(auto e : range(edges(in)))
    add_edge(source(e, in), target(e, in), out);
}

template<class Graph, class Generator>
void add_spider(Graph& G, unsigned legs, Generator generator) {
  unsigned n = num_vertices(G);
  unsigned cutoff = n / legs;
  auto range_iterator = boost::make_counting_iterator<int>;
  std::vector<int> path(range_iterator(0), range_iterator(n));
  std::shuffle(path.begin(), path.end(), generator);
  for(unsigned i = 0; i < n-1; ++i)
    add_edge_no_dup(path[i % cutoff == 0 ? 0 : i], path[i+1], G);
}

template<class Graph, class Generator>
void add_edges_uniform(Graph& G, double p, Generator generator, bool mst) {
  unsigned n = num_vertices(G);
  double connectedness = 20.0 / n;
  if(mst && p < connectedness) {
    typedef boost::property<boost::edge_weight_t, double> Weight;
    typedef boost::adjacency_list<boost::hash_setS, boost::vecS, boost::undirectedS, boost::no_property, Weight> WeightedGraph;
    typedef boost::graph_traits<WeightedGraph>::edge_descriptor WeightedEdge;
    std::uniform_real_distribution<> distribution(0, 1);
    auto trial = std::bind(distribution, generator);
    WeightedGraph g;
    for(unsigned i = 0; i < n; ++i) {
      for(unsigned j = i + 1; j < n; ++j) {
        auto w = trial();
        if(w < connectedness) add_edge(i, j, w, g);
        if(w < p) add_edge_no_dup(i, j, G);
      }
    }
    std::vector<WeightedEdge> t;
    kruskal_minimum_spanning_tree(g, std::back_inserter(t));
    for(auto e : t) add_edge_no_dup(source(e, g), target(e, g), G);
  } else {
    std::bernoulli_distribution distribution(p);
    auto trial = std::bind(distribution, generator);
    for(unsigned i = 0; i < n; ++i) {
      for(unsigned j = i + 1; j < n; ++j) {
        if(trial()) add_edge_no_dup(i, j, G);
      }
    }
  }
}

class Geometric {
  CGAL::Exact_predicates_inexact_constructions_kernel           typedef Kernel;
  CGAL::Triangulation_vertex_base_with_info_2<unsigned, Kernel> typedef Vertex_struct;
  CGAL::Triangulation_data_structure_2<Vertex_struct>           typedef Triangulation_struct;
  CGAL::Point_set_2<Kernel, Triangulation_struct>               typedef Delaunay;
  Delaunay::Point                                               typedef Point;

  Delaunay D;

public:
  template<class Generator>
  Geometric(int n, Generator generator) {
    // Choose random points in square [0, 1) x [0, 1)
    std::uniform_real_distribution<> distribution(0, 1);
    auto r = std::bind(distribution, generator);
    // Generate index for every point
    int counter = 0;
    std::function<std::pair<Point, int>()> f =
      [&]() {return std::make_pair(Point(r(), r()), counter++); };
    // Initialize triangulation with n points
    D = Delaunay(boost::make_function_input_iterator(f, 0),
                 boost::make_function_input_iterator(f, n));
  }

  template<class Graph>
  void add_random_geometric(Graph& G, double d) {
    CGAL::Circle_2<Kernel>  typedef Circle;
    Delaunay::Vertex_handle typedef Vertex_handle;
    // Query each point for other points lying in the circle
    for(auto v : range(D.finite_vertices_begin(), D.finite_vertices_end()))
      D.range_search(Circle(v.point(), d*d), boost::make_function_output_iterator(
          [&](Vertex_handle u){
            if(v.info() < u->info())
              add_edge_no_dup(v.info(), u->info(), G);
      }));
  }

  template<class Graph>
  void add_mst(Graph& G) {
    typedef boost::property<boost::edge_weight_t, Kernel::FT> Weight;
    typedef boost::adjacency_list<boost::hash_setS, boost::vecS, boost::undirectedS, boost::no_property, Weight> WeightedGraph;
    typedef boost::graph_traits<WeightedGraph>::edge_descriptor WeightedEdge;

    Delaunay::Finite_vertices_iterator vit;
    Delaunay::Vertex_circulator vc, done;

    WeightedGraph g;

    for(vit = D.finite_vertices_begin(); vit != D.finite_vertices_end(); ++vit) {
      unsigned s = vit->info();
      done = vc = vit->incident_vertices();
      if(vc != 0) do {
        if(D.is_infinite(vc)) continue;
        unsigned d = vc->info();
        add_edge(s, d, CGAL::squared_distance(vit->point(), vc->point()), g);
      } while(++vc != done);
    }

    std::vector<WeightedEdge> mst;
    kruskal_minimum_spanning_tree(g, std::back_inserter(mst));
    for(auto e : mst) add_edge_no_dup(source(e, g), target(e, g), G);
  }
};

template<class G>
bool is_planar(G const & gIn) {
  return boyer_myrvold_planarity_test(gIn);
}

//a class to hold the coordinates of the straight line embedding
struct coord_t {
  std::size_t x;
  std::size_t y;
};

template<class G>
std::vector<coord_t> straight_line_drawing(G const & gIn) {
  using namespace boost;

  typedef adjacency_list<vecS, vecS, undirectedS, property<vertex_index_t, int>,
      property<edge_index_t, int> > Graph;

  Graph g;
  copy_edges(gIn, g);

  //Define the storage type for the planar embedding
  typedef std::vector<std::vector<graph_traits<Graph>::edge_descriptor>> embedding_storage_t;
  typedef iterator_property_map<embedding_storage_t::iterator,
      property_map<Graph, vertex_index_t>::type> embedding_t;

  make_connected(g);

  // Create the planar embedding
  embedding_storage_t embedding_storage(num_vertices(g));
  embedding_t embedding(embedding_storage.begin(), get(vertex_index, g));

  boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
                               boyer_myrvold_params::embedding = embedding);

  //Initialize the interior edge index
  property_map<Graph, edge_index_t>::type e_index = get(edge_index, g);
  graph_traits<Graph>::edges_size_type edge_count = 0;
  graph_traits<Graph>::edge_iterator ei, ei_end;
  for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
    put(e_index, *ei, edge_count++);

  make_biconnected_planar(g, embedding);

  // Re-initialize the edge index, since we just added a few edges
  edge_count = 0;
  for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
    put(e_index, *ei, edge_count++);

  //Test for planarity again; compute the planar embedding as a side-effect
  boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
                               boyer_myrvold_params::embedding = embedding);

  make_maximal_planar(g, embedding);

  //Test for planarity again; compute the planar embedding as a side-effect
  boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g,
                               boyer_myrvold_params::embedding = embedding);

  // Find a canonical ordering
  std::vector<typename graph_traits<Graph>::vertex_descriptor> ordering;
  planar_canonical_ordering(g, embedding, std::back_inserter(ordering));

  //Set up a property map to hold the mapping from vertices to coord_t's
  typedef std::vector<coord_t> drawing_storage_t;
  typedef boost::iterator_property_map<drawing_storage_t::iterator,
      property_map<Graph, vertex_index_t>::type> drawing_t;

  drawing_storage_t drawing_storage(num_vertices(g));
  drawing_t drawing(drawing_storage.begin(), get(vertex_index, g));

  // Compute the straight line drawing
  chrobak_payne_straight_line_drawing(g, embedding, ordering.begin(),
                                      ordering.end(), drawing);

  return drawing_storage;
}
<commit_msg>code formatting<commit_after>// (C) 2014 Arek Olek

#pragma once

#include <algorithm>
#include <functional>
#include <utility>
#include <vector>

#include <boost/iterator/counting_iterator.hpp>
#include <boost/iterator/function_input_iterator.hpp>
#include <boost/function_output_iterator.hpp>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/connected_components.hpp>
#include <boost/graph/kruskal_min_spanning_tree.hpp>
#include <boost/graph/boyer_myrvold_planar_test.hpp>
#include <boost/graph/planar_canonical_ordering.hpp>
#include <boost/graph/chrobak_payne_drawing.hpp>
#include <boost/graph/make_connected.hpp>
#include <boost/graph/make_biconnected_planar.hpp>
#include <boost/graph/make_maximal_planar.hpp>

#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Triangulation_vertex_base_with_info_2.h>
#include <CGAL/Point_set_2.h>
#include <CGAL/squared_distance_2.h>

#include "range.hpp"

template<class Graph>
unsigned num_internal(Graph const & G) {
  unsigned internal = 0;
  for (auto v : range(vertices(G)))
    internal += out_degree(v, G) > 1;
  return internal;
}

template<class Graph>
unsigned upper_bound(Graph const & G) {
  return std::min(num_internal(G), (unsigned) num_vertices(G) - 2);
}

template<class Graph>
bool is_connected(Graph const & G) {
  std::vector<int> component(num_vertices(G));
  return connected_components(G, &component[0]) == 1;
}

template<class G>
void add_edge_no_dup(typename boost::graph_traits<G>::vertex_descriptor v,
                     typename boost::graph_traits<G>::vertex_descriptor u,
                     G& g) {
  if (!edge(v, u, g).second) add_edge(v, u, g);
}

template<class Input, class Output>
void copy_edges(const Input& in, Output& out) {
  for (auto e : range(edges(in)))
    add_edge(source(e, in), target(e, in), out);
}

template<class Graph, class Generator>
void add_spider(Graph& G, unsigned legs, Generator generator) {
  unsigned n = num_vertices(G);
  unsigned cutoff = n / legs;
  auto range_iterator = boost::make_counting_iterator<int>;
  std::vector<int> path(range_iterator(0), range_iterator(n));
  std::shuffle(path.begin(), path.end(), generator);
  for (unsigned i = 0; i < n - 1; ++i)
    add_edge_no_dup(path[i % cutoff == 0 ? 0 : i], path[i + 1], G);
}

template<class Graph, class Generator>
void add_edges_uniform(Graph& G, double p, Generator generator, bool mst) {
  unsigned n = num_vertices(G);
  double connectedness = 20.0 / n;
  if (mst && p < connectedness) {
    typedef boost::property<boost::edge_weight_t, double> Weight;
    typedef boost::adjacency_list<boost::hash_setS, boost::vecS, boost::undirectedS, boost::no_property, Weight> WeightedGraph;
    typedef boost::graph_traits<WeightedGraph>::edge_descriptor WeightedEdge;
    std::uniform_real_distribution<> distribution(0, 1);
    auto trial = std::bind(distribution, generator);
    WeightedGraph g;
    for (unsigned i = 0; i < n; ++i) {
      for (unsigned j = i + 1; j < n; ++j) {
        auto w = trial();
        if (w < connectedness) add_edge(i, j, w, g);
        if (w < p) add_edge_no_dup(i, j, G);
      }
    }
    std::vector<WeightedEdge> t;
    kruskal_minimum_spanning_tree(g, std::back_inserter(t));
    for (auto e : t)
      add_edge_no_dup(source(e, g), target(e, g), G);
  } else {
    std::bernoulli_distribution distribution(p);
    auto trial = std::bind(distribution, generator);
    for (unsigned i = 0; i < n; ++i) {
      for (unsigned j = i + 1; j < n; ++j) {
        if (trial()) add_edge_no_dup(i, j, G);
      }
    }
  }
}

class Geometric {
  CGAL::Exact_predicates_inexact_constructions_kernel typedef Kernel;
  CGAL::Triangulation_vertex_base_with_info_2<unsigned, Kernel> typedef Vertex_struct;
  CGAL::Triangulation_data_structure_2<Vertex_struct> typedef Triangulation_struct;
  CGAL::Point_set_2<Kernel, Triangulation_struct> typedef Delaunay;
  Delaunay::Point typedef Point;

  Delaunay D;

 public:
  template<class Generator>
  Geometric(int n, Generator generator) {
    // Choose random points in square [0, 1) x [0, 1)
    std::uniform_real_distribution<> distribution(0, 1);
    auto r = std::bind(distribution, generator);
    // Generate index for every point
    int counter = 0;
    std::function<std::pair<Point, int>()> f = [&]() {return std::make_pair(Point(r(), r()), counter++);};
    // Initialize triangulation with n points
    D = Delaunay(boost::make_function_input_iterator(f, 0), boost::make_function_input_iterator(f, n));
  }

  template<class Graph>
  void add_random_geometric(Graph& G, double d) {
    CGAL::Circle_2<Kernel> typedef Circle;
    Delaunay::Vertex_handle typedef Vertex_handle;
    // Query each point for other points lying in the circle
    for (auto v : range(D.finite_vertices_begin(), D.finite_vertices_end()))
      D.range_search(Circle(v.point(), d * d), boost::make_function_output_iterator([&](Vertex_handle u) {
        if (v.info() < u->info()) add_edge_no_dup(v.info(), u->info(), G);
      }));
  }

  template<class Graph>
  void add_mst(Graph& G) {
    typedef boost::property<boost::edge_weight_t, Kernel::FT> Weight;
    typedef boost::adjacency_list<boost::hash_setS, boost::vecS, boost::undirectedS, boost::no_property, Weight> WeightedGraph;
    typedef boost::graph_traits<WeightedGraph>::edge_descriptor WeightedEdge;

    Delaunay::Finite_vertices_iterator vit;
    Delaunay::Vertex_circulator vc, done;

    WeightedGraph g;

    for (vit = D.finite_vertices_begin(); vit != D.finite_vertices_end(); ++vit) {
      unsigned s = vit->info();
      done = vc = vit->incident_vertices();
      if (vc != 0) do {
        if (D.is_infinite(vc)) continue;
        unsigned d = vc->info();
        add_edge(s, d, CGAL::squared_distance(vit->point(), vc->point()), g);
      } while (++vc != done);
    }

    std::vector<WeightedEdge> mst;
    kruskal_minimum_spanning_tree(g, std::back_inserter(mst));
    for (auto e : mst)
      add_edge_no_dup(source(e, g), target(e, g), G);
  }
};

template<class G>
bool is_planar(G const & gIn) {
  return boyer_myrvold_planarity_test(gIn);
}

//a class to hold the coordinates of the straight line embedding
struct coord_t {
  std::size_t x;
  std::size_t y;
};

template<class G>
std::vector<coord_t> straight_line_drawing(G const & gIn) {
  using namespace boost;

  typedef adjacency_list<vecS, vecS, undirectedS, property<vertex_index_t, int>, property<edge_index_t, int> > Graph;

  Graph g;
  copy_edges(gIn, g);

  //Define the storage type for the planar embedding
  typedef std::vector<std::vector<graph_traits<Graph>::edge_descriptor>> embedding_storage_t;
  typedef iterator_property_map<embedding_storage_t::iterator, property_map<Graph, vertex_index_t>::type> embedding_t;

  make_connected(g);

  // Create the planar embedding
  embedding_storage_t embedding_storage(num_vertices(g));
  embedding_t embedding(embedding_storage.begin(), get(vertex_index, g));

  boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g, boyer_myrvold_params::embedding = embedding);

  //Initialize the interior edge index
  property_map<Graph, edge_index_t>::type e_index = get(edge_index, g);
  graph_traits<Graph>::edges_size_type edge_count = 0;
  graph_traits<Graph>::edge_iterator ei, ei_end;
  for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
    put(e_index, *ei, edge_count++);

  make_biconnected_planar(g, embedding);

  // Re-initialize the edge index, since we just added a few edges
  edge_count = 0;
  for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei)
    put(e_index, *ei, edge_count++);

  //Test for planarity again; compute the planar embedding as a side-effect
  boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g, boyer_myrvold_params::embedding = embedding);

  make_maximal_planar(g, embedding);

  //Test for planarity again; compute the planar embedding as a side-effect
  boyer_myrvold_planarity_test(boyer_myrvold_params::graph = g, boyer_myrvold_params::embedding = embedding);

  // Find a canonical ordering
  std::vector<typename graph_traits<Graph>::vertex_descriptor> ordering;
  planar_canonical_ordering(g, embedding, std::back_inserter(ordering));

  //Set up a property map to hold the mapping from vertices to coord_t's
  typedef std::vector<coord_t> drawing_storage_t;
  typedef boost::iterator_property_map<drawing_storage_t::iterator, property_map<Graph, vertex_index_t>::type> drawing_t;

  drawing_storage_t drawing_storage(num_vertices(g));
  drawing_t drawing(drawing_storage.begin(), get(vertex_index, g));

  // Compute the straight line drawing
  chrobak_payne_straight_line_drawing(g, embedding, ordering.begin(), ordering.end(), drawing);

  return drawing_storage;
}
<|endoftext|>


<commit_before>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/common_runtime/direct_session.h"

#include <map>
#include <string>
#include <unordered_map>
#include <vector>

#include "tensorflow/core/common_runtime/device_factory.h"
#include "tensorflow/core/framework/allocator.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_testutil.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/graph/costmodel.h"
#include "tensorflow/core/graph/graph.h"
#include "tensorflow/core/graph/testlib.h"
#include "tensorflow/core/kernels/ops_util.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/core/status_test_util.h"
#include "tensorflow/core/lib/core/threadpool.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/public/session.h"
#include "tensorflow/core/public/session_options.h"
#include "tensorflow/core/util/device_name_utils.h"

namespace tensorflow {
namespace {

TEST(DirectSessionWithTrackingAllocTest, CostModelTest) {
  EnableCPUAllocatorFullStats(true);

  Graph graph(OpRegistry::Global());

  Tensor a_tensor(DT_FLOAT, TensorShape({2, 2}));
  test::FillValues<float>(&a_tensor, {3, 2, -1, 0});
  Node* a = test::graph::Constant(&graph, a_tensor);
  a->set_assigned_device_name("/job:localhost/replica:0/task:0/cpu:0");

  Tensor x_tensor(DT_FLOAT, TensorShape({2, 1}));
  test::FillValues<float>(&x_tensor, {1, 1});
  Node* x = test::graph::Constant(&graph, x_tensor);
  x->set_assigned_device_name("/job:localhost/replica:0/task:0/cpu:1");

  // y = A * x
  Node* y = test::graph::Matmul(&graph, a, x, false, false);
  y->set_assigned_device_name("/job:localhost/replica:0/task:0/cpu:0");

  Node* y_neg = test::graph::Unary(&graph, "Neg", y);
  y_neg->set_assigned_device_name("/job:localhost/replica:0/task:0/cpu:1");

  GraphDef def;
  test::graph::ToGraphDef(&graph, &def);

  SessionOptions options;
  (*options.config.mutable_device_count())["CPU"] = 2;
  options.config.mutable_graph_options()->set_build_cost_model(true);
  std::unique_ptr<Session> session(NewSession(options));
  TF_ASSERT_OK(session->Create(def));
  std::vector<std::pair<string, Tensor>> inputs;

  // Request two targets: one fetch output and one non-fetched output.
  std::vector<string> output_names = {y->name() + ":0"};
  std::vector<string> target_nodes = {y_neg->name()};
  std::vector<Tensor> outputs;
  Status s = session->Run(inputs, output_names, target_nodes, &outputs);
  TF_ASSERT_OK(s);

  DirectSession* ds = static_cast<DirectSession*>(session.get());
  int graph_cnt = 0;
  CostModelManager::CostModelMap cost_models;
  ds->ExportCostModels(&cost_models);
  for (auto& it : cost_models) {
    const Graph* g = (it).first;
    const CostModel* cm = (it).second;
    for (Node* node : g->nodes()) {
      if (node->name() == y->name()) {
        EXPECT_LE(8, cm->MaxMemorySize(node, 0));
        EXPECT_EQ(5, cm->AllocationId(node, 0));
      } else if (node->name() == y_neg->name()) {
        EXPECT_LE(8, cm->MaxMemorySize(node, 0));
        EXPECT_EQ(7, cm->AllocationId(node, 0));
      }
      // Check the execution time. Since it's highly variable, we'll
      // use a large window: anything between 1 and 10000 microseconds is
      // considered ok.
      EXPECT_LE(1, cm->MaxExecutionTime(node));
      EXPECT_GE(10000, cm->MaxExecutionTime(node));
    }
    graph_cnt++;
  }
  // We should have 2 cost models since we have 2 cpu devices.
  ASSERT_EQ(2, graph_cnt);
}

}  // namespace
}  // namespace tensorflow
<commit_msg>Change test for MaxExecutionTime to allow time 0, in direct_session_with_tracking_alloc_test. Change: 124970170<commit_after>/* Copyright 2015 The TensorFlow Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/

#include "tensorflow/core/common_runtime/direct_session.h"

#include <map>
#include <string>
#include <unordered_map>
#include <vector>

#include "tensorflow/core/common_runtime/device_factory.h"
#include "tensorflow/core/framework/allocator.h"
#include "tensorflow/core/framework/graph.pb.h"
#include "tensorflow/core/framework/op_kernel.h"
#include "tensorflow/core/framework/tensor.h"
#include "tensorflow/core/framework/tensor_testutil.h"
#include "tensorflow/core/framework/types.pb.h"
#include "tensorflow/core/graph/costmodel.h"
#include "tensorflow/core/graph/graph.h"
#include "tensorflow/core/graph/testlib.h"
#include "tensorflow/core/kernels/ops_util.h"
#include "tensorflow/core/lib/core/errors.h"
#include "tensorflow/core/lib/core/status.h"
#include "tensorflow/core/lib/core/status_test_util.h"
#include "tensorflow/core/lib/core/threadpool.h"
#include "tensorflow/core/platform/test.h"
#include "tensorflow/core/public/session.h"
#include "tensorflow/core/public/session_options.h"
#include "tensorflow/core/util/device_name_utils.h"

namespace tensorflow {
namespace {

TEST(DirectSessionWithTrackingAllocTest, CostModelTest) {
  EnableCPUAllocatorFullStats(true);

  Graph graph(OpRegistry::Global());

  Tensor a_tensor(DT_FLOAT, TensorShape({2, 2}));
  test::FillValues<float>(&a_tensor, {3, 2, -1, 0});
  Node* a = test::graph::Constant(&graph, a_tensor);
  a->set_assigned_device_name("/job:localhost/replica:0/task:0/cpu:0");

  Tensor x_tensor(DT_FLOAT, TensorShape({2, 1}));
  test::FillValues<float>(&x_tensor, {1, 1});
  Node* x = test::graph::Constant(&graph, x_tensor);
  x->set_assigned_device_name("/job:localhost/replica:0/task:0/cpu:1");

  // y = A * x
  Node* y = test::graph::Matmul(&graph, a, x, false, false);
  y->set_assigned_device_name("/job:localhost/replica:0/task:0/cpu:0");

  Node* y_neg = test::graph::Unary(&graph, "Neg", y);
  y_neg->set_assigned_device_name("/job:localhost/replica:0/task:0/cpu:1");

  GraphDef def;
  test::graph::ToGraphDef(&graph, &def);

  SessionOptions options;
  (*options.config.mutable_device_count())["CPU"] = 2;
  options.config.mutable_graph_options()->set_build_cost_model(true);
  std::unique_ptr<Session> session(NewSession(options));
  TF_ASSERT_OK(session->Create(def));
  std::vector<std::pair<string, Tensor>> inputs;

  // Request two targets: one fetch output and one non-fetched output.
  std::vector<string> output_names = {y->name() + ":0"};
  std::vector<string> target_nodes = {y_neg->name()};
  std::vector<Tensor> outputs;
  Status s = session->Run(inputs, output_names, target_nodes, &outputs);
  TF_ASSERT_OK(s);

  DirectSession* ds = static_cast<DirectSession*>(session.get());
  int graph_cnt = 0;
  CostModelManager::CostModelMap cost_models;
  ds->ExportCostModels(&cost_models);
  for (auto& it : cost_models) {
    const Graph* g = (it).first;
    const CostModel* cm = (it).second;
    for (Node* node : g->nodes()) {
      if (node->name() == y->name()) {
        EXPECT_LE(8, cm->MaxMemorySize(node, 0));
        EXPECT_EQ(5, cm->AllocationId(node, 0));
      } else if (node->name() == y_neg->name()) {
        EXPECT_LE(8, cm->MaxMemorySize(node, 0));
        EXPECT_EQ(7, cm->AllocationId(node, 0));
      }
      // Check the execution time. Since it's highly variable, we'll
      // use a large window: anything between 1 and 10000 microseconds is
      // considered ok.
      EXPECT_LE(0, cm->MaxExecutionTime(node));
      EXPECT_GE(10000, cm->MaxExecutionTime(node));
    }
    graph_cnt++;
  }
  // We should have 2 cost models since we have 2 cpu devices.
  ASSERT_EQ(2, graph_cnt);
}

}  // namespace
}  // namespace tensorflow
<|endoftext|>


<commit_before>    /*************************************************************************
 *
 *  $RCSfile: slideshow.cxx,v $
 *
 *  $Revision: 1.4 $
 *
 *  last change: $Author: rt $ $Date: 2005-03-30 10:30:44 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 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
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/
#ifndef _SD_SLIDESHOW_HXX
#include "slideshow.hxx"
#endif

#ifndef _SD_SLIDESHOWIMPL_HXX_
#include "slideshowimpl.hxx"
#endif

using namespace ::sd;
using namespace ::rtl;

Slideshow::Slideshow( ViewShell* pViewSh, ::sd::View* pView, SdDrawDocument* pDoc )
: mpImpl( new SlideshowImpl(pViewSh, pView, pDoc ) )
{
    mpImpl->acquire();
}

Slideshow::~Slideshow()
{
    dispose();
    mpImpl->release();
}

bool Slideshow::startShow( PresentationSettings* pPresSettings )
{
    return mpImpl->startShow( pPresSettings );
}

bool Slideshow::startPreview(
        const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& xDrawPage,
        const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xAnimationNode,
        ::Window* pParent )
{
    if( mpImpl->startPreview( xDrawPage, xAnimationNode, pParent ) )
    {
        ShowWindow* pShowWindow = mpImpl->getShowWindow();
        if( pShowWindow )
            pShowWindow->setSlideshow( this );
        return true;
    }
    else
    {
        return false;
    }
}

void Slideshow::paint( const Rectangle& rRect )
{
    mpImpl->paint( rRect );
}

void Slideshow::stopShow()
{
    mpImpl->stopShow();
}

void Slideshow::dispose()
{
    mpImpl->stopShow();
}

ShowWindow* Slideshow::getShowWindow()
{
    return mpImpl->mpShowWindow;
}

int Slideshow::getAnimationMode()
{
    return mpImpl->meAnimationMode;
}

void Slideshow::jumpToPageIndex( sal_Int32 nPageIndex )
{
    mpImpl->jumpToPageIndex( nPageIndex );
}

void Slideshow::jumpToPageNumber( sal_Int32 nPageNumber )
{
    mpImpl->jumpToPageNumber( nPageNumber );
}

sal_Int32 Slideshow::getCurrentPageNumber()
{
    return mpImpl->getCurrentPageNumber();
}

sal_Int32 Slideshow::getCurrentPageIndex()
{
    return mpImpl->getCurrentPageIndex();
}

void Slideshow::jumpToBookmark( const String& sBookmark )
{
}

void Slideshow::setRehearseTimings( bool bRehearseTimings )
{
    mpImpl->mbRehearseTimings = bRehearseTimings;
}

bool Slideshow::isFullScreen()
{
    return mpImpl->maPresSettings.mbFullScreen;
}

void Slideshow::resize( const Size &rSize )
{
    mpImpl->resize( rSize );
}

void Slideshow::activate()
{
    mpImpl->activate();
}

void Slideshow::deactivate()
{
    mpImpl->deactivate();
}

void Slideshow::setWindow( sd::Window* pWindow )
{
}

bool Slideshow::requestHelp(const HelpEvent& rHEvt)
{
    return false;
}

bool Slideshow::isTerminated()
{
    return !mpImpl->mxShow.is();
}

bool Slideshow::keyInput(const KeyEvent& rKEvt)
{
    return mpImpl->keyInput(rKEvt);
}

void Slideshow::mouseButtonDown(const MouseEvent& rMEvt)
{
}

void Slideshow::mouseMove(const MouseEvent& rMEvt)
{
}

void Slideshow::mouseButtonUp(const MouseEvent& rMEvt)
{
    mpImpl->mouseButtonUp( rMEvt );
}

void Slideshow::command(const CommandEvent& rCEvt)
{
}

bool Slideshow::isAlwaysOnTop()
{
    return mpImpl->maPresSettings.mbAlwaysOnTop;
}

bool Slideshow::pause( bool bPause )
{
    return mpImpl->pause( bPause );
}

void Slideshow::receiveRequest(SfxRequest& rReq)
{
    mpImpl->receiveRequest( rReq );
}

sal_Int32 Slideshow::getFirstPageNumber()
{
    return mpImpl->getFirstPageNumber();
}

sal_Int32 Slideshow::getLastPageNumber()
{
    return mpImpl->getLastPageNumber();
}

bool Slideshow::isEndless()
{
    return mpImpl->isEndless();
}

bool Slideshow::isDrawingPossible()
{
    return mpImpl->isDrawingPossible();
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.4.154); FILE MERGED 2005/09/05 13:24:12 rt 1.4.154.1: #i54170# Change license header: remove SISSL<commit_after>    /*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: slideshow.cxx,v $
 *
 *  $Revision: 1.5 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-09 06:07:28 $
 *
 *  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
 *
 ************************************************************************/
#ifndef _SD_SLIDESHOW_HXX
#include "slideshow.hxx"
#endif

#ifndef _SD_SLIDESHOWIMPL_HXX_
#include "slideshowimpl.hxx"
#endif

using namespace ::sd;
using namespace ::rtl;

Slideshow::Slideshow( ViewShell* pViewSh, ::sd::View* pView, SdDrawDocument* pDoc )
: mpImpl( new SlideshowImpl(pViewSh, pView, pDoc ) )
{
    mpImpl->acquire();
}

Slideshow::~Slideshow()
{
    dispose();
    mpImpl->release();
}

bool Slideshow::startShow( PresentationSettings* pPresSettings )
{
    return mpImpl->startShow( pPresSettings );
}

bool Slideshow::startPreview(
        const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XDrawPage >& xDrawPage,
        const ::com::sun::star::uno::Reference< ::com::sun::star::animations::XAnimationNode >& xAnimationNode,
        ::Window* pParent )
{
    if( mpImpl->startPreview( xDrawPage, xAnimationNode, pParent ) )
    {
        ShowWindow* pShowWindow = mpImpl->getShowWindow();
        if( pShowWindow )
            pShowWindow->setSlideshow( this );
        return true;
    }
    else
    {
        return false;
    }
}

void Slideshow::paint( const Rectangle& rRect )
{
    mpImpl->paint( rRect );
}

void Slideshow::stopShow()
{
    mpImpl->stopShow();
}

void Slideshow::dispose()
{
    mpImpl->stopShow();
}

ShowWindow* Slideshow::getShowWindow()
{
    return mpImpl->mpShowWindow;
}

int Slideshow::getAnimationMode()
{
    return mpImpl->meAnimationMode;
}

void Slideshow::jumpToPageIndex( sal_Int32 nPageIndex )
{
    mpImpl->jumpToPageIndex( nPageIndex );
}

void Slideshow::jumpToPageNumber( sal_Int32 nPageNumber )
{
    mpImpl->jumpToPageNumber( nPageNumber );
}

sal_Int32 Slideshow::getCurrentPageNumber()
{
    return mpImpl->getCurrentPageNumber();
}

sal_Int32 Slideshow::getCurrentPageIndex()
{
    return mpImpl->getCurrentPageIndex();
}

void Slideshow::jumpToBookmark( const String& sBookmark )
{
}

void Slideshow::setRehearseTimings( bool bRehearseTimings )
{
    mpImpl->mbRehearseTimings = bRehearseTimings;
}

bool Slideshow::isFullScreen()
{
    return mpImpl->maPresSettings.mbFullScreen;
}

void Slideshow::resize( const Size &rSize )
{
    mpImpl->resize( rSize );
}

void Slideshow::activate()
{
    mpImpl->activate();
}

void Slideshow::deactivate()
{
    mpImpl->deactivate();
}

void Slideshow::setWindow( sd::Window* pWindow )
{
}

bool Slideshow::requestHelp(const HelpEvent& rHEvt)
{
    return false;
}

bool Slideshow::isTerminated()
{
    return !mpImpl->mxShow.is();
}

bool Slideshow::keyInput(const KeyEvent& rKEvt)
{
    return mpImpl->keyInput(rKEvt);
}

void Slideshow::mouseButtonDown(const MouseEvent& rMEvt)
{
}

void Slideshow::mouseMove(const MouseEvent& rMEvt)
{
}

void Slideshow::mouseButtonUp(const MouseEvent& rMEvt)
{
    mpImpl->mouseButtonUp( rMEvt );
}

void Slideshow::command(const CommandEvent& rCEvt)
{
}

bool Slideshow::isAlwaysOnTop()
{
    return mpImpl->maPresSettings.mbAlwaysOnTop;
}

bool Slideshow::pause( bool bPause )
{
    return mpImpl->pause( bPause );
}

void Slideshow::receiveRequest(SfxRequest& rReq)
{
    mpImpl->receiveRequest( rReq );
}

sal_Int32 Slideshow::getFirstPageNumber()
{
    return mpImpl->getFirstPageNumber();
}

sal_Int32 Slideshow::getLastPageNumber()
{
    return mpImpl->getLastPageNumber();
}

bool Slideshow::isEndless()
{
    return mpImpl->isEndless();
}

bool Slideshow::isDrawingPossible()
{
    return mpImpl->isDrawingPossible();
}

<|endoftext|>


<commit_before>#include"IScoreboard.h"

class Scoreboard : public IScoreboard {

};
<commit_msg>removed IScoreboard.cpp. Wrong file setup<commit_after><|endoftext|>