<commit_before>#include "qhexcursor.h"
#include "qhexdocument.h"
#include <QWidget>
#include <QPoint>

#define currentDocument static_cast<QHexDocument*>(this->parent())
//#define currentContainer static_cast<QWidget*>(currentDocument->parent())

const int QHexCursor::CURSOR_BLINK_INTERVAL = 500; // 5ms

QHexCursor::QHexCursor(QObject *parent) : QObject(parent), _selectedpart(QHexCursor::HexPart), _insertionmode(QHexCursor::OverwriteMode)
{
    this->_cursorx = this->_cursory = 0;
    this->_selectionstart = this->_offset = this->_bitindex = 0;
    this->_timerid = this->startTimer(QHexCursor::CURSOR_BLINK_INTERVAL);
}

QHexCursor::~QHexCursor()
{
    this->killTimer(this->_timerid);
}

QPoint QHexCursor::position() const
{
    return QPoint(this->_cursorx, this->_cursory);
}

sinteger_t QHexCursor::cursorX() const
{
    return this->_cursorx;
}

sinteger_t QHexCursor::cursorY() const
{
    return this->_cursory;
}

integer_t QHexCursor::offset() const
{
    return this->_offset;
}

integer_t QHexCursor::bitIndex() const
{
    return this->_bitindex;
}

integer_t QHexCursor::selectionStart() const
{
    return qMin(this->_offset, this->_selectionstart);
}

integer_t QHexCursor::selectionEnd() const
{
    return qMax(this->_offset, this->_selectionstart);
}

integer_t QHexCursor::selectionLength() const
{
    return this->selectionEnd() - this->selectionStart();
}

QHexCursor::SelectedPart QHexCursor::selectedPart() const
{
    return this->_selectedpart;
}

QHexCursor::InsertionMode QHexCursor::insertionMode() const
{
    return this->_insertionmode;
}

bool QHexCursor::isAddressPartSelected() const
{
    return this->_selectedpart == QHexCursor::AddressPart;
}

bool QHexCursor::isHexPartSelected() const
{
    return this->_selectedpart == QHexCursor::HexPart;
}

bool QHexCursor::isAsciiPartSelected() const
{
    return this->_selectedpart == QHexCursor::AsciiPart;
}

bool QHexCursor::isInsertMode() const
{
    return this->_insertionmode == QHexCursor::InsertMode;
}

bool QHexCursor::isOverwriteMode() const
{
    return this->_insertionmode == QHexCursor::OverwriteMode;
}

bool QHexCursor::hasSelection() const
{
    return this->_offset != this->_selectionstart;
}

bool QHexCursor::blinking() const
{
    return this->_blink;
}

bool QHexCursor::isSelected(integer_t offset) const
{
    if(this->_offset == this->_selectionstart)
        return false;

    return (offset >= this->selectionStart()) && (offset < this->selectionEnd());
}

void QHexCursor::selectStart()
{
    this->setOffset(0);
}

void QHexCursor::selectEnd()
{
    this->setOffset(currentDocument->length());
}

void QHexCursor::selectAll()
{
    this->setSelectionEnd(0);
    this->setOffset(currentDocument->length());
}

void QHexCursor::setPosition(sinteger_t x, sinteger_t y)
{
    if((this->_cursorx == x) && (this->_cursory == y))
        return;

    this->_cursorx = x;
    this->_cursory = y;
    emit positionChanged();
}

void QHexCursor::setOffset(integer_t offset)
{
    this->setOffset(offset, 0);
}

void QHexCursor::setOffset(integer_t offset, integer_t bitindex)
{
    offset = qMin(offset, currentDocument->length()); // Check EOF
    this->_selectionstart = offset;
    this->_bitindex = bitindex;

    this->setSelectionEnd(offset);
}

void QHexCursor::setSelectionEnd(integer_t offset)
{
    offset = qMin(offset, currentDocument->length()); // Check EOF

    if(this->_selectionstart != this->_offset)
        emit selectionChanged();

    this->_offset = offset;
    emit offsetChanged();
}

void QHexCursor::setSelection(integer_t startoffset, integer_t endoffset)
{
    this->setOffset(startoffset);
    this->setSelectionEnd(endoffset);
}

void QHexCursor::setSelectionRange(integer_t startoffset, integer_t length)
{
    this->setSelection(startoffset, startoffset + length);
}

void QHexCursor::setSelectedPart(QHexCursor::SelectedPart sp)
{
    if(sp == this->_selectedpart)
        return;

    this->_selectedpart = sp;
    emit selectedPartChanged();
}

void QHexCursor::clearSelection()
{
    if(this->_selectionstart == this->_offset)
        return;

    this->_selectionstart = this->_offset;
    emit selectionChanged();
}

bool QHexCursor::removeSelection()
{
    if(!this->hasSelection())
        return false;

    currentDocument->remove(this->selectionStart(), this->selectionLength());
    this->clearSelection();
    return true;
}

void QHexCursor::moveOffset(sinteger_t c)
{
    if(!c)
        return;

    integer_t offset = this->_offset + c;

    if(offset >= currentDocument->length())
        offset = c > 0 ? currentDocument->length() : 0;

    this->setOffset(offset);
}

void QHexCursor::moveSelection(sinteger_t c)
{
    if(!c)
        return;

    integer_t offset = this->_offset + c;

    if(offset >= currentDocument->length())
        offset = c > 0 ? currentDocument->length() : 0;

    this->setSelectionEnd(offset);
}

void QHexCursor::blink(bool b)
{
    this->_blink = b;
    emit blinkChanged();
}

void QHexCursor::switchMode()
{
    if(this->_insertionmode == QHexCursor::OverwriteMode)
        this->_insertionmode = QHexCursor::InsertMode;
    else
        this->_insertionmode = QHexCursor::OverwriteMode;

    emit insertionModeChanged();
}

void QHexCursor::timerEvent(QTimerEvent *event)
{
    Q_UNUSED(event);

    this->_blink = !this->_blink;
    emit blinkChanged();
}
<commit_msg>QHexCursor: Relax selectionChanged signal rules<commit_after>#include "qhexcursor.h"
#include "qhexdocument.h"
#include <QWidget>
#include <QPoint>

#define currentDocument static_cast<QHexDocument*>(this->parent())
//#define currentContainer static_cast<QWidget*>(currentDocument->parent())

const int QHexCursor::CURSOR_BLINK_INTERVAL = 500; // 5ms

QHexCursor::QHexCursor(QObject *parent) : QObject(parent), _selectedpart(QHexCursor::HexPart), _insertionmode(QHexCursor::OverwriteMode)
{
    this->_cursorx = this->_cursory = 0;
    this->_selectionstart = this->_offset = this->_bitindex = 0;
    this->_timerid = this->startTimer(QHexCursor::CURSOR_BLINK_INTERVAL);
}

QHexCursor::~QHexCursor()
{
    this->killTimer(this->_timerid);
}

QPoint QHexCursor::position() const
{
    return QPoint(this->_cursorx, this->_cursory);
}

sinteger_t QHexCursor::cursorX() const
{
    return this->_cursorx;
}

sinteger_t QHexCursor::cursorY() const
{
    return this->_cursory;
}

integer_t QHexCursor::offset() const
{
    return this->_offset;
}

integer_t QHexCursor::bitIndex() const
{
    return this->_bitindex;
}

integer_t QHexCursor::selectionStart() const
{
    return qMin(this->_offset, this->_selectionstart);
}

integer_t QHexCursor::selectionEnd() const
{
    return qMax(this->_offset, this->_selectionstart);
}

integer_t QHexCursor::selectionLength() const
{
    return this->selectionEnd() - this->selectionStart();
}

QHexCursor::SelectedPart QHexCursor::selectedPart() const
{
    return this->_selectedpart;
}

QHexCursor::InsertionMode QHexCursor::insertionMode() const
{
    return this->_insertionmode;
}

bool QHexCursor::isAddressPartSelected() const
{
    return this->_selectedpart == QHexCursor::AddressPart;
}

bool QHexCursor::isHexPartSelected() const
{
    return this->_selectedpart == QHexCursor::HexPart;
}

bool QHexCursor::isAsciiPartSelected() const
{
    return this->_selectedpart == QHexCursor::AsciiPart;
}

bool QHexCursor::isInsertMode() const
{
    return this->_insertionmode == QHexCursor::InsertMode;
}

bool QHexCursor::isOverwriteMode() const
{
    return this->_insertionmode == QHexCursor::OverwriteMode;
}

bool QHexCursor::hasSelection() const
{
    return this->_offset != this->_selectionstart;
}

bool QHexCursor::blinking() const
{
    return this->_blink;
}

bool QHexCursor::isSelected(integer_t offset) const
{
    if(this->_offset == this->_selectionstart)
        return false;

    return (offset >= this->selectionStart()) && (offset < this->selectionEnd());
}

void QHexCursor::selectStart()
{
    this->setOffset(0);
}

void QHexCursor::selectEnd()
{
    this->setOffset(currentDocument->length());
}

void QHexCursor::selectAll()
{
    this->setSelectionEnd(0);
    this->setOffset(currentDocument->length());
}

void QHexCursor::setPosition(sinteger_t x, sinteger_t y)
{
    if((this->_cursorx == x) && (this->_cursory == y))
        return;

    this->_cursorx = x;
    this->_cursory = y;
    emit positionChanged();
}

void QHexCursor::setOffset(integer_t offset)
{
    this->setOffset(offset, 0);
}

void QHexCursor::setOffset(integer_t offset, integer_t bitindex)
{
    offset = qMin(offset, currentDocument->length()); // Check EOF
    this->_selectionstart = offset;
    this->_bitindex = bitindex;

    this->setSelectionEnd(offset);
}

void QHexCursor::setSelectionEnd(integer_t offset)
{
    offset = qMin(offset, currentDocument->length()); // Check EOF
    emit selectionChanged();

    this->_offset = offset;
    emit offsetChanged();
}

void QHexCursor::setSelection(integer_t startoffset, integer_t endoffset)
{
    this->setOffset(startoffset);
    this->setSelectionEnd(endoffset);
}

void QHexCursor::setSelectionRange(integer_t startoffset, integer_t length)
{
    this->setSelection(startoffset, startoffset + length);
}

void QHexCursor::setSelectedPart(QHexCursor::SelectedPart sp)
{
    if(sp == this->_selectedpart)
        return;

    this->_selectedpart = sp;
    emit selectedPartChanged();
}

void QHexCursor::clearSelection()
{
    if(this->_selectionstart == this->_offset)
        return;

    this->_selectionstart = this->_offset;
    emit selectionChanged();
}

bool QHexCursor::removeSelection()
{
    if(!this->hasSelection())
        return false;

    currentDocument->remove(this->selectionStart(), this->selectionLength());
    this->clearSelection();
    return true;
}

void QHexCursor::moveOffset(sinteger_t c)
{
    if(!c)
        return;

    integer_t offset = this->_offset + c;

    if(offset >= currentDocument->length())
        offset = c > 0 ? currentDocument->length() : 0;

    this->setOffset(offset);
}

void QHexCursor::moveSelection(sinteger_t c)
{
    if(!c)
        return;

    integer_t offset = this->_offset + c;

    if(offset >= currentDocument->length())
        offset = c > 0 ? currentDocument->length() : 0;

    this->setSelectionEnd(offset);
}

void QHexCursor::blink(bool b)
{
    this->_blink = b;
    emit blinkChanged();
}

void QHexCursor::switchMode()
{
    if(this->_insertionmode == QHexCursor::OverwriteMode)
        this->_insertionmode = QHexCursor::InsertMode;
    else
        this->_insertionmode = QHexCursor::OverwriteMode;

    emit insertionModeChanged();
}

void QHexCursor::timerEvent(QTimerEvent *event)
{
    Q_UNUSED(event);

    this->_blink = !this->_blink;
    emit blinkChanged();
}
<|endoftext|>


<commit_before>#pragma once

#include "cql3/result_set.hh"

#include "transport/event.hh"

#include "core/shared_ptr.hh"
#include "core/sstring.hh"

namespace transport {

namespace messages {

class result_message {
public:
    class visitor;

    virtual ~result_message() {}

    virtual void accept(visitor&) = 0;

    //
    // Message types:
    //
    class void_message;
    class set_keyspace;
    class prepared;
    class schema_change;
    class rows;
};

class result_message::visitor {
public:
    virtual void visit(const result_message::void_message&) = 0;
    virtual void visit(const result_message::set_keyspace&) = 0;
    virtual void visit(const result_message::prepared&) = 0;
    virtual void visit(const result_message::schema_change&) = 0;
    virtual void visit(const result_message::rows&) = 0;
};

class result_message::void_message : public result_message {
public:
    virtual void accept(result_message::visitor& v) override {
        v.visit(*this);
    }
};

class result_message::set_keyspace : public result_message {
private:
    sstring _keyspace;
public:
    set_keyspace(const sstring& keyspace)
        : _keyspace{keyspace}
    { }

    const sstring& get_keyspace() const {
        return _keyspace;
    }

    virtual void accept(result_message::visitor& v) override {
        v.visit(*this);
    }
};

class result_message::prepared : public result_message {
private:
    bytes _id;
   ::shared_ptr<cql3::statements::parsed_statement::prepared> _prepared;
public:
    prepared(const bytes& id, ::shared_ptr<cql3::statements::parsed_statement::prepared> prepared)
        : _id{id}
        , _prepared{prepared}
    { }

    const bytes& get_id() const {
        return _id;
    }

    const ::shared_ptr<cql3::statements::parsed_statement::prepared>& get_prepared() const {
        return _prepared;
    }

    virtual void accept(result_message::visitor& v) override {
        v.visit(*this);
    }
};

class result_message::schema_change : public result_message {
private:
    shared_ptr<event::schema_change> _change;
public:
    schema_change(shared_ptr<event::schema_change> change)
        : _change{change}
    { }

    shared_ptr<event::schema_change> get_change() const {
        return _change;
    }

    virtual void accept(result_message::visitor& v) override {
        v.visit(*this);
    }
};

class result_message::rows : public result_message {
private:
    std::unique_ptr<cql3::result_set> _rs;
public:
    rows(std::unique_ptr<cql3::result_set> rs) : _rs(std::move(rs)) {}

    const cql3::result_set& rs() const {
        return *_rs;
    }

    virtual void accept(result_message::visitor& v) override {
        v.visit(*this);
    }
};

}

}
<commit_msg>transport: Add missing include<commit_after>#pragma once

#include "cql3/result_set.hh"
#include "cql3/statements/parsed_statement.hh"

#include "transport/event.hh"

#include "core/shared_ptr.hh"
#include "core/sstring.hh"

namespace transport {

namespace messages {

class result_message {
public:
    class visitor;

    virtual ~result_message() {}

    virtual void accept(visitor&) = 0;

    //
    // Message types:
    //
    class void_message;
    class set_keyspace;
    class prepared;
    class schema_change;
    class rows;
};

class result_message::visitor {
public:
    virtual void visit(const result_message::void_message&) = 0;
    virtual void visit(const result_message::set_keyspace&) = 0;
    virtual void visit(const result_message::prepared&) = 0;
    virtual void visit(const result_message::schema_change&) = 0;
    virtual void visit(const result_message::rows&) = 0;
};

class result_message::void_message : public result_message {
public:
    virtual void accept(result_message::visitor& v) override {
        v.visit(*this);
    }
};

class result_message::set_keyspace : public result_message {
private:
    sstring _keyspace;
public:
    set_keyspace(const sstring& keyspace)
        : _keyspace{keyspace}
    { }

    const sstring& get_keyspace() const {
        return _keyspace;
    }

    virtual void accept(result_message::visitor& v) override {
        v.visit(*this);
    }
};

class result_message::prepared : public result_message {
private:
    bytes _id;
   ::shared_ptr<cql3::statements::parsed_statement::prepared> _prepared;
public:
    prepared(const bytes& id, ::shared_ptr<cql3::statements::parsed_statement::prepared> prepared)
        : _id{id}
        , _prepared{prepared}
    { }

    const bytes& get_id() const {
        return _id;
    }

    const ::shared_ptr<cql3::statements::parsed_statement::prepared>& get_prepared() const {
        return _prepared;
    }

    virtual void accept(result_message::visitor& v) override {
        v.visit(*this);
    }
};

class result_message::schema_change : public result_message {
private:
    shared_ptr<event::schema_change> _change;
public:
    schema_change(shared_ptr<event::schema_change> change)
        : _change{change}
    { }

    shared_ptr<event::schema_change> get_change() const {
        return _change;
    }

    virtual void accept(result_message::visitor& v) override {
        v.visit(*this);
    }
};

class result_message::rows : public result_message {
private:
    std::unique_ptr<cql3::result_set> _rs;
public:
    rows(std::unique_ptr<cql3::result_set> rs) : _rs(std::move(rs)) {}

    const cql3::result_set& rs() const {
        return *_rs;
    }

    virtual void accept(result_message::visitor& v) override {
        v.visit(*this);
    }
};

}

}
<|endoftext|>


<commit_before>//******************************************************************************
///
/// @file base/image/hdr.cpp
///
/// Implementation of Radiance RGBE High Dynamic Range (HDR) image file
/// handling.
///
/// @author Christopher Cason
/// @author Christoph Lipka
/// @author Based on MegaPOV HDR code written by Mael and Christoph Hormann
///
/// @copyright
/// @parblock
///
/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
/// Copyright 1991-2016 Persistence of Vision Raytracer Pty. Ltd.
///
/// POV-Ray is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License as
/// published by the Free Software Foundation, either version 3 of the
/// License, or (at your option) any later version.
///
/// POV-Ray 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 Affero General Public License for more details.
///
/// You should have received a copy of the GNU Affero General Public License
/// along with this program.  If not, see <http://www.gnu.org/licenses/>.
///
/// ----------------------------------------------------------------------------
///
/// POV-Ray is based on the popular DKB raytracer version 2.12.
/// DKBTrace was originally written by David K. Buck.
/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
///
/// @endparblock
///
//******************************************************************************

// Unit header file must be the first file included within POV-Ray *.cpp files (pulls in config)
#include "base/image/hdr.h"

// Standard C++ header files
#include <string>

// Boost header files
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>

// POV-Ray base header files
#include "base/fileinputoutput.h"
#include "base/types.h"
#include "base/image/metadata.h"

// this must be the last file included
#include "base/povdebug.h"

namespace pov_base
{

namespace HDR
{

/*****************************************************************************
* Local preprocessor defines
******************************************************************************/

#define  MINELEN        8       /* minimum scanline length for encoding */
#define  MAXELEN        0x7fff  /* maximum scanline length for encoding */
#define  MINRUN         4       /* minimum run length */

/*****************************************************************************
* Local typedefs
******************************************************************************/

struct Messages
{
    vector<string> warnings;
    string error;
};

typedef unsigned char RGBE[4]; // red, green, blue, exponent

void GetRGBE(RGBE rgbe, const Image *image, int col, int row, const GammaCurvePtr& gamma, DitherHandler* dither);
void SetRGBE(const unsigned char *scanline, Image *image, int row, int width, const GammaCurvePtr& gamma);
void ReadOldLine(unsigned char *scanline, int width, IStream *file);

/*****************************************************************************
* Code
******************************************************************************/
void GetRGBE(RGBE rgbe, const Image *image, int col, int row, const GammaCurvePtr& gamma, DitherHandler* dh)
{
    DitherHandler::OffsetInfo linOff, encOff;
    dh->getOffset(col,row,linOff,encOff);

    RGBColour rgbColour;
    GetEncodedRGBValue(image, col, row, gamma, rgbColour);

    rgbColour += linOff.getRGB();
    RadianceHDRColour rgbeColour(rgbColour,encOff.getRGB());
    for (int i = 0; i < 4; i ++)
        rgbe[i] = (*rgbeColour)[i];

    rgbColour -= RGBColour(rgbeColour);
    linOff.setRGB(rgbColour);
    dh->setError(col,row,linOff);
}

void SetRGBE(const unsigned char *scanline, Image *image, int row, int width, const GammaCurvePtr& gamma)
{
    for(int i = 0; i < width; i++)
    {
        RadianceHDRColour rgbeColour;
        for (int j = 0; j < 4; j ++)
            (*rgbeColour)[j] = scanline[j];
        SetEncodedRGBValue(image, i, row, gamma, RGBColour(rgbeColour));
        scanline += 4;
    }
}

void ReadOldLine(unsigned char *scanline, int width, IStream *file)
{
    int rshift = 0;
    unsigned char b;

    while(width > 0)
    {
        scanline[0] = file->Read_Byte();
        scanline[1] = file->Read_Byte();
        scanline[2] = file->Read_Byte();

        // NB EOF won't be set at this point even if the last read obtained the
        // final byte in the file (we need to read another byte for that to happen).
        if(*file == false)
            throw POV_EXCEPTION(kFileDataErr, "Invalid HDR file (unexpected EOF)");

        if(!file->Read_Byte(b))
            return;

        scanline[3] = b;

        if((scanline[0] == 1) && (scanline[1] == 1) && (scanline[2] == 1))
        {
            for(int i = scanline[3] << rshift; i > 0; i--)
            {
                memcpy(scanline, scanline - 4, 4);
                scanline += 4;
                width--;
            }
            rshift += 8;
        }
        else
        {
            scanline += 4;
            width--;
            rshift = 0;
        }
    }
}

Image *Read(IStream *file, const Image::ReadOptions& options)
{
    char line[2048];
    char *s;
    char s1[3];
    char s2[3];
    unsigned char b;
    unsigned char val;
    float e;
    float exposure = 1.0;
    unsigned int width;
    unsigned int height;
    Image *image = NULL;
    Image::ImageDataType imagetype = options.itype;

    // Radiance HDR files store linear color values by default, so never convert unless the user overrides
    // (e.g. to handle a non-compliant file).
    GammaCurvePtr gamma;
    if (options.gammacorrect)
    {
        if (options.gammaOverride)
            gamma = TranscodingGammaCurve::Get(options.workingGamma, options.defaultGamma);
        else
            gamma = TranscodingGammaCurve::Get(options.workingGamma, NeutralGammaCurve::Get());
    }

    while(*file)
    {
        if((file->getline(line, sizeof(line)) == false) || (line[0] == '-') || (line[0] == '+'))
            break;

        // TODO: what do we do with exposure?
        if(strncmp(line, "EXPOSURE", 8) == 0)
        {
            if((s = strchr(line, '=')) != NULL)
            {
                if(sscanf(s + 1, "%f", &e) == 1)
                    exposure *= e;
            }
        }
    }

    if(sscanf(line, "%2[+-XY] %u %2[+-XY] %u\n", s1, &height, s2, &width) != 4)
        throw POV_EXCEPTION(kFileDataErr, "Bad HDR file header");

    if(imagetype == Image::Undefined)
        imagetype = Image::RGBFT_Float;

    image = Image::Create(width, height, imagetype);
    // NB: HDR files don't use alpha, so premultiplied vs. non-premultiplied is not an issue

    boost::scoped_array<unsigned char> scanline(new unsigned char[4 * width]);
    for(int row = 0; row < height; row++)
    {
        // determine scanline type
        if((width < MINELEN) | (width > MAXELEN))
        {
            ReadOldLine(scanline.get(), width, file);
            SetRGBE(scanline.get(), image, row, width, gamma);
            continue;
        }

        if(file->Read_Byte(b) == false)
            throw POV_EXCEPTION(kFileDataErr, "Incomplete HDR file");

        if(b != 2)
        {
            file->UnRead_Byte(b);

            ReadOldLine(scanline.get(), width, file);
            SetRGBE(scanline.get(), image, row, width, gamma);
            continue;
        }

        scanline[1] = file->Read_Byte();
        scanline[2] = file->Read_Byte();

        if(file->Read_Byte(b) == false)
            throw POV_EXCEPTION(kFileDataErr, "Incomplete or invalid HDR file");

        if((scanline[1] != 2) || ((scanline[2] & 128) != 0))
        {
            scanline[0] = 2;
            scanline[3] = b;

            ReadOldLine(scanline.get() + 4, width - 1, file);
            SetRGBE(scanline.get(), image, row, width, gamma);
            continue;
        }

        if((((int) scanline[2] << 8) | b) != width)
            throw POV_EXCEPTION(kFileDataErr, "Invalid HDR file (length mismatch)");

        for(int i = 0; i < 4; i++)
        {
            for(int j = 0; j < width; )
            {
                if(file->Read_Byte(b) == false)
                    throw POV_EXCEPTION(kFileDataErr, "Invalid HDR file (unexpected EOF)");

                if(b > 128)
                {
                    // run
                    b &= 127;

                    if(file->Read_Byte(val) == false)
                        throw POV_EXCEPTION(kFileDataErr, "Invalid HDR file (unexpected EOF)");

                    while(b--)
                        scanline[j++ * 4 + i] = (unsigned char) val;
                }
                else
                {
                    while(b--)
                    {
                        if(file->Read_Byte(val) == false)
                            throw POV_EXCEPTION(kFileDataErr, "Invalid HDR file (unexpected EOF)");

                        scanline[j++ * 4 + i] = (unsigned char) val;
                    }
                }
            }
        }

        SetRGBE(scanline.get(), image, row, width, gamma);
    }

    return image;
}

void Write(OStream *file, const Image *image, const Image::WriteOptions& options)
{
    int width = image->GetWidth();
    int height = image->GetHeight();
    int cnt = 1;
    int c2;
    RGBE rgbe;
    GammaCurvePtr gamma = TranscodingGammaCurve::Get(options.workingGamma, NeutralGammaCurve::Get());
    DitherHandler* dither = options.dither.get();

    Metadata meta;
    file->printf("#?RADIANCE\n");
    file->printf("SOFTWARE=%s\n", meta.getSoftware().c_str());
    file->printf("CREATION_TIME=%s\n" ,meta.getDateTime().c_str());
    if (!meta.getComment1().empty())
        file->printf("COMMENT=%s\n", meta.getComment1().c_str());
    if (!meta.getComment2().empty())
        file->printf("COMMENT=%s\n", meta.getComment2().c_str());
    if (!meta.getComment3().empty())
        file->printf("COMMENT=%s\n", meta.getComment3().c_str());
    if (!meta.getComment4().empty())
        file->printf("COMMENT=%s\n", meta.getComment4().c_str());

    file->printf("FORMAT=32-bit_rle_rgbe\n");
    file->printf("\n");
    file->printf("-Y %d +X %d\n", height, width);

    boost::scoped_array<RGBE> scanline(new RGBE[width]);

    for(int row = 0; row < height; row++)
    {
        if((width < MINELEN) | (width > MAXELEN))
        {
            for(int col = 0; col < width; col++)
            {
                GetRGBE(rgbe, image, col, row, gamma, dither);

                if(file->write(&rgbe, sizeof(RGBE)) == false)
                    throw POV_EXCEPTION(kFileDataErr, "Failed to write data to HDR file");
            }
        }
        else
        {
            // put magic header
            file->Write_Byte(2);
            file->Write_Byte(2);
            file->Write_Byte(width >> 8);
            file->Write_Byte(width & 255);

            // convert pixels
            for(int col = 0; col < width; col++)
                GetRGBE(scanline[col], image, col, row, gamma, dither);

            // put components seperately
            for(int i = 0; i < 4; i++)
            {
                for(int col = 0; col < width; col += cnt)
                {
                    int beg = 0;

                    // find next run
                    for(beg = col; beg < width; beg += cnt)
                    {
                        cnt = 1;
                        while((cnt < 127) && (beg + cnt < width) && (scanline[beg + cnt][i] == scanline[beg][i]))
                            cnt++;

                        // long enough ?
                        if(cnt >= MINRUN)
                            break;
                    }

                    if(beg - col > 1 && beg - col < MINRUN)
                    {
                        c2 = col + 1;
                        while(scanline[c2++][i] == scanline[col][i])
                        {
                            if(c2 == beg)
                            {
                                // short run
                                file->Write_Byte(128 + beg - col);

                                if(file->Write_Byte(scanline[col][i]) == false)
                                    throw POV_EXCEPTION(kFileDataErr, "Failed to write data to HDR file");

                                col = beg;
                                break;
                            }
                        }
                    }
                    while(col < beg)
                    {
                        // write non-run
                        if((c2 = beg - col) > 128)
                            c2 = 128;

                        file->Write_Byte(c2);

                        while(c2--)
                        {
                            if(file->Write_Byte(scanline[col++][i]) == false)
                                throw POV_EXCEPTION(kFileDataErr, "Failed to write data to HDR file");
                        }
                    }
                    if(cnt >= MINRUN)
                    {
                        // write run
                        file->Write_Byte(128 + cnt);

                        if(file->Write_Byte(scanline[beg][i]) == false)
                            throw POV_EXCEPTION(kFileDataErr, "Failed to write data to HDR file");
                    }
                    else
                        cnt = 0;
                }
            }
        }
    }
}

} // end of namespace HDR

} // end of namespace pov_base

<commit_msg>Replaced broken comparison in hdr.cpp<commit_after>//******************************************************************************
///
/// @file base/image/hdr.cpp
///
/// Implementation of Radiance RGBE High Dynamic Range (HDR) image file
/// handling.
///
/// @author Christopher Cason
/// @author Christoph Lipka
/// @author Based on MegaPOV HDR code written by Mael and Christoph Hormann
///
/// @copyright
/// @parblock
///
/// Persistence of Vision Ray Tracer ('POV-Ray') version 3.7.
/// Copyright 1991-2016 Persistence of Vision Raytracer Pty. Ltd.
///
/// POV-Ray is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License as
/// published by the Free Software Foundation, either version 3 of the
/// License, or (at your option) any later version.
///
/// POV-Ray 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 Affero General Public License for more details.
///
/// You should have received a copy of the GNU Affero General Public License
/// along with this program.  If not, see <http://www.gnu.org/licenses/>.
///
/// ----------------------------------------------------------------------------
///
/// POV-Ray is based on the popular DKB raytracer version 2.12.
/// DKBTrace was originally written by David K. Buck.
/// DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
///
/// @endparblock
///
//******************************************************************************

// Unit header file must be the first file included within POV-Ray *.cpp files (pulls in config)
#include "base/image/hdr.h"

// Standard C++ header files
#include <string>

// Boost header files
#include <boost/scoped_ptr.hpp>
#include <boost/scoped_array.hpp>

// POV-Ray base header files
#include "base/fileinputoutput.h"
#include "base/types.h"
#include "base/image/metadata.h"

// this must be the last file included
#include "base/povdebug.h"

namespace pov_base
{

namespace HDR
{

/*****************************************************************************
* Local preprocessor defines
******************************************************************************/

#define  MINELEN        8       /* minimum scanline length for encoding */
#define  MAXELEN        0x7fff  /* maximum scanline length for encoding */
#define  MINRUN         4       /* minimum run length */

/*****************************************************************************
* Local typedefs
******************************************************************************/

struct Messages
{
    vector<string> warnings;
    string error;
};

typedef unsigned char RGBE[4]; // red, green, blue, exponent

void GetRGBE(RGBE rgbe, const Image *image, int col, int row, const GammaCurvePtr& gamma, DitherHandler* dither);
void SetRGBE(const unsigned char *scanline, Image *image, int row, int width, const GammaCurvePtr& gamma);
void ReadOldLine(unsigned char *scanline, int width, IStream *file);

/*****************************************************************************
* Code
******************************************************************************/
void GetRGBE(RGBE rgbe, const Image *image, int col, int row, const GammaCurvePtr& gamma, DitherHandler* dh)
{
    DitherHandler::OffsetInfo linOff, encOff;
    dh->getOffset(col,row,linOff,encOff);

    RGBColour rgbColour;
    GetEncodedRGBValue(image, col, row, gamma, rgbColour);

    rgbColour += linOff.getRGB();
    RadianceHDRColour rgbeColour(rgbColour,encOff.getRGB());
    for (int i = 0; i < 4; i ++)
        rgbe[i] = (*rgbeColour)[i];

    rgbColour -= RGBColour(rgbeColour);
    linOff.setRGB(rgbColour);
    dh->setError(col,row,linOff);
}

void SetRGBE(const unsigned char *scanline, Image *image, int row, int width, const GammaCurvePtr& gamma)
{
    for(int i = 0; i < width; i++)
    {
        RadianceHDRColour rgbeColour;
        for (int j = 0; j < 4; j ++)
            (*rgbeColour)[j] = scanline[j];
        SetEncodedRGBValue(image, i, row, gamma, RGBColour(rgbeColour));
        scanline += 4;
    }
}

void ReadOldLine(unsigned char *scanline, int width, IStream *file)
{
    int rshift = 0;
    unsigned char b;

    while(width > 0)
    {
        scanline[0] = file->Read_Byte();
        scanline[1] = file->Read_Byte();
        scanline[2] = file->Read_Byte();

        // NB EOF won't be set at this point even if the last read obtained the
        // final byte in the file (we need to read another byte for that to happen).
        if(!*file)
            throw POV_EXCEPTION(kFileDataErr, "Invalid HDR file (unexpected EOF)");

        if(!file->Read_Byte(b))
            return;

        scanline[3] = b;

        if((scanline[0] == 1) && (scanline[1] == 1) && (scanline[2] == 1))
        {
            for(int i = scanline[3] << rshift; i > 0; i--)
            {
                memcpy(scanline, scanline - 4, 4);
                scanline += 4;
                width--;
            }
            rshift += 8;
        }
        else
        {
            scanline += 4;
            width--;
            rshift = 0;
        }
    }
}

Image *Read(IStream *file, const Image::ReadOptions& options)
{
    char line[2048];
    char *s;
    char s1[3];
    char s2[3];
    unsigned char b;
    unsigned char val;
    float e;
    float exposure = 1.0;
    unsigned int width;
    unsigned int height;
    Image *image = NULL;
    Image::ImageDataType imagetype = options.itype;

    // Radiance HDR files store linear color values by default, so never convert unless the user overrides
    // (e.g. to handle a non-compliant file).
    GammaCurvePtr gamma;
    if (options.gammacorrect)
    {
        if (options.gammaOverride)
            gamma = TranscodingGammaCurve::Get(options.workingGamma, options.defaultGamma);
        else
            gamma = TranscodingGammaCurve::Get(options.workingGamma, NeutralGammaCurve::Get());
    }

    while(*file)
    {
        if((file->getline(line, sizeof(line)) == false) || (line[0] == '-') || (line[0] == '+'))
            break;

        // TODO: what do we do with exposure?
        if(strncmp(line, "EXPOSURE", 8) == 0)
        {
            if((s = strchr(line, '=')) != NULL)
            {
                if(sscanf(s + 1, "%f", &e) == 1)
                    exposure *= e;
            }
        }
    }

    if(sscanf(line, "%2[+-XY] %u %2[+-XY] %u\n", s1, &height, s2, &width) != 4)
        throw POV_EXCEPTION(kFileDataErr, "Bad HDR file header");

    if(imagetype == Image::Undefined)
        imagetype = Image::RGBFT_Float;

    image = Image::Create(width, height, imagetype);
    // NB: HDR files don't use alpha, so premultiplied vs. non-premultiplied is not an issue

    boost::scoped_array<unsigned char> scanline(new unsigned char[4 * width]);
    for(int row = 0; row < height; row++)
    {
        // determine scanline type
        if((width < MINELEN) | (width > MAXELEN))
        {
            ReadOldLine(scanline.get(), width, file);
            SetRGBE(scanline.get(), image, row, width, gamma);
            continue;
        }

        if(file->Read_Byte(b) == false)
            throw POV_EXCEPTION(kFileDataErr, "Incomplete HDR file");

        if(b != 2)
        {
            file->UnRead_Byte(b);

            ReadOldLine(scanline.get(), width, file);
            SetRGBE(scanline.get(), image, row, width, gamma);
            continue;
        }

        scanline[1] = file->Read_Byte();
        scanline[2] = file->Read_Byte();

        if(file->Read_Byte(b) == false)
            throw POV_EXCEPTION(kFileDataErr, "Incomplete or invalid HDR file");

        if((scanline[1] != 2) || ((scanline[2] & 128) != 0))
        {
            scanline[0] = 2;
            scanline[3] = b;

            ReadOldLine(scanline.get() + 4, width - 1, file);
            SetRGBE(scanline.get(), image, row, width, gamma);
            continue;
        }

        if((((int) scanline[2] << 8) | b) != width)
            throw POV_EXCEPTION(kFileDataErr, "Invalid HDR file (length mismatch)");

        for(int i = 0; i < 4; i++)
        {
            for(int j = 0; j < width; )
            {
                if(file->Read_Byte(b) == false)
                    throw POV_EXCEPTION(kFileDataErr, "Invalid HDR file (unexpected EOF)");

                if(b > 128)
                {
                    // run
                    b &= 127;

                    if(file->Read_Byte(val) == false)
                        throw POV_EXCEPTION(kFileDataErr, "Invalid HDR file (unexpected EOF)");

                    while(b--)
                        scanline[j++ * 4 + i] = (unsigned char) val;
                }
                else
                {
                    while(b--)
                    {
                        if(file->Read_Byte(val) == false)
                            throw POV_EXCEPTION(kFileDataErr, "Invalid HDR file (unexpected EOF)");

                        scanline[j++ * 4 + i] = (unsigned char) val;
                    }
                }
            }
        }

        SetRGBE(scanline.get(), image, row, width, gamma);
    }

    return image;
}

void Write(OStream *file, const Image *image, const Image::WriteOptions& options)
{
    int width = image->GetWidth();
    int height = image->GetHeight();
    int cnt = 1;
    int c2;
    RGBE rgbe;
    GammaCurvePtr gamma = TranscodingGammaCurve::Get(options.workingGamma, NeutralGammaCurve::Get());
    DitherHandler* dither = options.dither.get();

    Metadata meta;
    file->printf("#?RADIANCE\n");
    file->printf("SOFTWARE=%s\n", meta.getSoftware().c_str());
    file->printf("CREATION_TIME=%s\n" ,meta.getDateTime().c_str());
    if (!meta.getComment1().empty())
        file->printf("COMMENT=%s\n", meta.getComment1().c_str());
    if (!meta.getComment2().empty())
        file->printf("COMMENT=%s\n", meta.getComment2().c_str());
    if (!meta.getComment3().empty())
        file->printf("COMMENT=%s\n", meta.getComment3().c_str());
    if (!meta.getComment4().empty())
        file->printf("COMMENT=%s\n", meta.getComment4().c_str());

    file->printf("FORMAT=32-bit_rle_rgbe\n");
    file->printf("\n");
    file->printf("-Y %d +X %d\n", height, width);

    boost::scoped_array<RGBE> scanline(new RGBE[width]);

    for(int row = 0; row < height; row++)
    {
        if((width < MINELEN) | (width > MAXELEN))
        {
            for(int col = 0; col < width; col++)
            {
                GetRGBE(rgbe, image, col, row, gamma, dither);

                if(file->write(&rgbe, sizeof(RGBE)) == false)
                    throw POV_EXCEPTION(kFileDataErr, "Failed to write data to HDR file");
            }
        }
        else
        {
            // put magic header
            file->Write_Byte(2);
            file->Write_Byte(2);
            file->Write_Byte(width >> 8);
            file->Write_Byte(width & 255);

            // convert pixels
            for(int col = 0; col < width; col++)
                GetRGBE(scanline[col], image, col, row, gamma, dither);

            // put components seperately
            for(int i = 0; i < 4; i++)
            {
                for(int col = 0; col < width; col += cnt)
                {
                    int beg = 0;

                    // find next run
                    for(beg = col; beg < width; beg += cnt)
                    {
                        cnt = 1;
                        while((cnt < 127) && (beg + cnt < width) && (scanline[beg + cnt][i] == scanline[beg][i]))
                            cnt++;

                        // long enough ?
                        if(cnt >= MINRUN)
                            break;
                    }

                    if(beg - col > 1 && beg - col < MINRUN)
                    {
                        c2 = col + 1;
                        while(scanline[c2++][i] == scanline[col][i])
                        {
                            if(c2 == beg)
                            {
                                // short run
                                file->Write_Byte(128 + beg - col);

                                if(file->Write_Byte(scanline[col][i]) == false)
                                    throw POV_EXCEPTION(kFileDataErr, "Failed to write data to HDR file");

                                col = beg;
                                break;
                            }
                        }
                    }
                    while(col < beg)
                    {
                        // write non-run
                        if((c2 = beg - col) > 128)
                            c2 = 128;

                        file->Write_Byte(c2);

                        while(c2--)
                        {
                            if(file->Write_Byte(scanline[col++][i]) == false)
                                throw POV_EXCEPTION(kFileDataErr, "Failed to write data to HDR file");
                        }
                    }
                    if(cnt >= MINRUN)
                    {
                        // write run
                        file->Write_Byte(128 + cnt);

                        if(file->Write_Byte(scanline[beg][i]) == false)
                            throw POV_EXCEPTION(kFileDataErr, "Failed to write data to HDR file");
                    }
                    else
                        cnt = 0;
                }
            }
        }
    }
}

} // end of namespace HDR

} // end of namespace pov_base

<|endoftext|>


<commit_before>#ifndef _UNTOOLS_UCBLOCKBYTES_HXX
#define _UNTOOLS_UCBLOCKBYTES_HXX

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_
#include <com/sun/star/io/XInputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XOutputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XSTREAM_HPP_
#include <com/sun/star/io/XStream.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENT_HPP_
#include <com/sun/star/ucb/XContent.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XSEEKABLE_HPP_
#include <com/sun/star/io/XSeekable.hpp>
#endif

#include <vos/thread.hxx>
#include <vos/conditn.hxx>
#include <vos/mutex.hxx>
#include <tools/stream.hxx>
#include <tools/link.hxx>
#include <tools/errcode.hxx>
#include <tools/datetime.hxx>

namespace utl
{
SV_DECL_REF( UcbLockBytes )

class UcbLockBytesHandler : public SvRefBase
{
    sal_Bool        m_bActive;
public:
    enum LoadHandlerItem
    {
        BEFOREWAIT,
        AFTERWAIT,
        DATA_AVAILABLE,
        DONE,
        CANCEL
    };

                    UcbLockBytesHandler()
                        : m_bActive( sal_True )
                    {}

    virtual void    Handle( LoadHandlerItem nWhich, UcbLockBytesRef xLockBytes ) = 0;
    void            Activate( BOOL bActivate = sal_True ) { m_bActive = bActivate; }
    sal_Bool        IsActive() const { return m_bActive; }
};

SV_DECL_IMPL_REF( UcbLockBytesHandler )

#define NS_UNO ::com::sun::star::uno
#define NS_IO ::com::sun::star::io
#define NS_UCB ::com::sun::star::ucb

class CommandThread_Impl;
class UcbLockBytes : public virtual SvLockBytes
{
    vos::OCondition         m_aInitialized;
    vos::OCondition         m_aTerminated;
    vos::OMutex             m_aMutex;

    String                  m_aContentType;
    String                  m_aRealURL;
    DateTime                m_aExpireDate;

    NS_UNO::Reference < NS_IO::XInputStream >  m_xInputStream;
    NS_UNO::Reference < NS_IO::XOutputStream > m_xOutputStream;
    NS_UNO::Reference < NS_IO::XSeekable >     m_xSeekable;
    CommandThread_Impl*     m_pCommandThread;
    UcbLockBytesHandlerRef  m_xHandler;

    sal_uInt32              m_nRead;
    sal_uInt32              m_nSize;
    ErrCode                 m_nError;

    sal_Bool                m_bTerminated : 1;
    sal_Bool                m_bDontClose : 1;
    sal_Bool                m_bStreamValid : 1;

    DECL_LINK(              DataAvailHdl, void * );

                            UcbLockBytes( UcbLockBytesHandler* pHandler=NULL );
protected:
    virtual                 ~UcbLockBytes (void);

public:

    static UcbLockBytesRef  CreateLockBytes( const NS_UNO::Reference < NS_UCB::XContent > xContent, StreamMode eMode,
                                            UcbLockBytesHandler* pHandler=0 );
    static UcbLockBytesRef  CreateInputLockBytes( const NS_UNO::Reference < NS_IO::XInputStream > xContent );

    // SvLockBytes
    virtual void            SetSynchronMode (BOOL bSynchron);
    virtual ErrCode         ReadAt ( ULONG nPos, void *pBuffer, ULONG nCount, ULONG *pRead) const;
    virtual ErrCode         WriteAt ( ULONG, const void*, ULONG, ULONG *pWritten);
    virtual ErrCode         Flush (void) const;
    virtual ErrCode         SetSize (ULONG);
    virtual ErrCode         Stat ( SvLockBytesStat *pStat, SvLockBytesStatFlag) const;

    void                    SetError( ErrCode nError )
                            { m_nError = nError; }

    ErrCode                 GetError() const
                            { return m_nError; }

    void                    Cancel();

    // the following properties are available when and after the first DataAvailable callback has been executed
    String                  GetContentType() const;
    String                  GetRealURL() const;
    DateTime                GetExpireDate() const;

#if __PRIVATE
    sal_Bool                setInputStream_Impl( const NS_UNO::Reference < NS_IO::XInputStream > &rxInputStream );
    sal_Bool                setStream_Impl( const NS_UNO::Reference < NS_IO::XStream > &rxStream );
    void                    terminate_Impl (void);

    NS_UNO::Reference < NS_IO::XInputStream > getInputStream_Impl() const
                            {
                                vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex );
                                return m_xInputStream;
                            }

    NS_UNO::Reference < NS_IO::XOutputStream > getOutputStream_Impl() const
                            {
                                vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex );
                                return m_xOutputStream;
                            }

    NS_UNO::Reference < NS_IO::XSeekable > getSeekable_Impl() const
                            {
                                vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex );
                                return m_xSeekable;
                            }

    sal_Bool                hasInputStream_Impl() const
                            {
                                vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex );
                                return m_xInputStream.is();
                            }

    void                    setCommandThread_Impl( CommandThread_Impl* pThread )
                            { m_pCommandThread = pThread; }

    void                    setDontClose_Impl()
                            { m_bDontClose = sal_True; }

    void                    SetContentType_Impl( const String& rType ) { m_aContentType = rType; }
    void                    SetRealURL_Impl( const String& rURL )  { m_aRealURL = rURL; }
    void                    SetExpireDate_Impl( const DateTime& rDateTime )  { m_aExpireDate = rDateTime; }
    void                    SetStreamValid_Impl();
#endif
};

SV_IMPL_REF( UcbLockBytes );

};

#endif
<commit_msg>#58628#,#65293# __PRIVATE -> _SOLAR__PRIVATE<commit_after>#ifndef _UNTOOLS_UCBLOCKBYTES_HXX
#define _UNTOOLS_UCBLOCKBYTES_HXX

#ifndef _COM_SUN_STAR_UNO_REFERENCE_HXX_
#include <com/sun/star/uno/Reference.hxx>
#endif
#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_
#include <com/sun/star/io/XInputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_
#include <com/sun/star/io/XOutputStream.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XSTREAM_HPP_
#include <com/sun/star/io/XStream.hpp>
#endif
#ifndef _COM_SUN_STAR_UCB_XCONTENT_HPP_
#include <com/sun/star/ucb/XContent.hpp>
#endif
#ifndef _COM_SUN_STAR_IO_XSEEKABLE_HPP_
#include <com/sun/star/io/XSeekable.hpp>
#endif

#include <vos/thread.hxx>
#include <vos/conditn.hxx>
#include <vos/mutex.hxx>
#include <tools/stream.hxx>
#include <tools/link.hxx>
#include <tools/errcode.hxx>
#include <tools/datetime.hxx>

namespace utl
{
SV_DECL_REF( UcbLockBytes )

class UcbLockBytesHandler : public SvRefBase
{
    sal_Bool        m_bActive;
public:
    enum LoadHandlerItem
    {
        BEFOREWAIT,
        AFTERWAIT,
        DATA_AVAILABLE,
        DONE,
        CANCEL
    };

                    UcbLockBytesHandler()
                        : m_bActive( sal_True )
                    {}

    virtual void    Handle( LoadHandlerItem nWhich, UcbLockBytesRef xLockBytes ) = 0;
    void            Activate( BOOL bActivate = sal_True ) { m_bActive = bActivate; }
    sal_Bool        IsActive() const { return m_bActive; }
};

SV_DECL_IMPL_REF( UcbLockBytesHandler )

#define NS_UNO ::com::sun::star::uno
#define NS_IO ::com::sun::star::io
#define NS_UCB ::com::sun::star::ucb

class CommandThread_Impl;
class UcbLockBytes : public virtual SvLockBytes
{
    vos::OCondition         m_aInitialized;
    vos::OCondition         m_aTerminated;
    vos::OMutex             m_aMutex;

    String                  m_aContentType;
    String                  m_aRealURL;
    DateTime                m_aExpireDate;

    NS_UNO::Reference < NS_IO::XInputStream >  m_xInputStream;
    NS_UNO::Reference < NS_IO::XOutputStream > m_xOutputStream;
    NS_UNO::Reference < NS_IO::XSeekable >     m_xSeekable;
    CommandThread_Impl*     m_pCommandThread;
    UcbLockBytesHandlerRef  m_xHandler;

    sal_uInt32              m_nRead;
    sal_uInt32              m_nSize;
    ErrCode                 m_nError;

    sal_Bool                m_bTerminated : 1;
    sal_Bool                m_bDontClose : 1;
    sal_Bool                m_bStreamValid : 1;

    DECL_LINK(              DataAvailHdl, void * );

                            UcbLockBytes( UcbLockBytesHandler* pHandler=NULL );
protected:
    virtual                 ~UcbLockBytes (void);

public:

    static UcbLockBytesRef  CreateLockBytes( const NS_UNO::Reference < NS_UCB::XContent > xContent, StreamMode eMode,
                                            UcbLockBytesHandler* pHandler=0 );
    static UcbLockBytesRef  CreateInputLockBytes( const NS_UNO::Reference < NS_IO::XInputStream > xContent );

    // SvLockBytes
    virtual void            SetSynchronMode (BOOL bSynchron);
    virtual ErrCode         ReadAt ( ULONG nPos, void *pBuffer, ULONG nCount, ULONG *pRead) const;
    virtual ErrCode         WriteAt ( ULONG, const void*, ULONG, ULONG *pWritten);
    virtual ErrCode         Flush (void) const;
    virtual ErrCode         SetSize (ULONG);
    virtual ErrCode         Stat ( SvLockBytesStat *pStat, SvLockBytesStatFlag) const;

    void                    SetError( ErrCode nError )
                            { m_nError = nError; }

    ErrCode                 GetError() const
                            { return m_nError; }

    void                    Cancel();

    // the following properties are available when and after the first DataAvailable callback has been executed
    String                  GetContentType() const;
    String                  GetRealURL() const;
    DateTime                GetExpireDate() const;

#if _SOLAR__PRIVATE
    sal_Bool                setInputStream_Impl( const NS_UNO::Reference < NS_IO::XInputStream > &rxInputStream );
    sal_Bool                setStream_Impl( const NS_UNO::Reference < NS_IO::XStream > &rxStream );
    void                    terminate_Impl (void);

    NS_UNO::Reference < NS_IO::XInputStream > getInputStream_Impl() const
                            {
                                vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex );
                                return m_xInputStream;
                            }

    NS_UNO::Reference < NS_IO::XOutputStream > getOutputStream_Impl() const
                            {
                                vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex );
                                return m_xOutputStream;
                            }

    NS_UNO::Reference < NS_IO::XSeekable > getSeekable_Impl() const
                            {
                                vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex );
                                return m_xSeekable;
                            }

    sal_Bool                hasInputStream_Impl() const
                            {
                                vos::OGuard aGuard( SAL_CONST_CAST(UcbLockBytes*, this)->m_aMutex );
                                return m_xInputStream.is();
                            }

    void                    setCommandThread_Impl( CommandThread_Impl* pThread )
                            { m_pCommandThread = pThread; }

    void                    setDontClose_Impl()
                            { m_bDontClose = sal_True; }

    void                    SetContentType_Impl( const String& rType ) { m_aContentType = rType; }
    void                    SetRealURL_Impl( const String& rURL )  { m_aRealURL = rURL; }
    void                    SetExpireDate_Impl( const DateTime& rDateTime )  { m_aExpireDate = rDateTime; }
    void                    SetStreamValid_Impl();
#endif
};

SV_IMPL_REF( UcbLockBytes );

};

#endif
<|endoftext|>


<commit_before>#include <iostream>

#include "vtrc-client-base/vtrc-client.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "vtrc-common/vtrc-exception.h"

#include "protocol/calculator.pb.h"
#include "calculator-iface.h"

#include "vtrc-condition-variable.h"
#include "vtrc-bind.h"
#include "vtrc-ref.h"
#include "vtrc-thread.h"
#include "vtrc-chrono.h"

using namespace vtrc::client;
using namespace vtrc::common;

void usage(  )
{
    std::cout
          << "Usage: \n\tcalculator_client <server ip> <server port>\n"
          << "or:\n\tcalculator_client <localname>\n"
          << "examples:\n"
          << "\tfor tcp: calculator_client 127.0.0.1 55555\n"
          << "\tfor unix: calculator_client /tmp/calculator.sock\n"
          << "\tfor win pipe: calculator_client \\\\.\\pipe\\calculator_pipe\n";
}

struct work_time {
    typedef vtrc::chrono::high_resolution_clock::time_point time_point;
    time_point start_;
    work_time( )
        :start_(vtrc::chrono::high_resolution_clock::now( ))
    {}
    ~work_time( )
    {
        time_point::duration stop(
                    vtrc::chrono::high_resolution_clock::now( ) - start_);
        std::cout << "Call time: " << stop << "\n";
    }
};

class variable_pool: public vtrc_example::variable_pool {

    std::map<std::string, double> variables_;
    unsigned server_calback_count_;

    void set_variable(::google::protobuf::RpcController* controller,
                 const ::vtrc_example::number* request,
                 ::vtrc_example::number* response,
                 ::google::protobuf::Closure* done)
    {
        ++server_calback_count_;

        closure_holder done_holder(done);
        std::string n(request->name( ));

        std::cout << "Server sets variable: '" << n << "'"
                  << " = " <<  request->value( )
                  << " thread id: " << vtrc::this_thread::get_id( ) << "\n";

        variables_[n] = request->value( );
    }

    void get_variable(::google::protobuf::RpcController* controller,
                 const ::vtrc_example::number* request,
                 ::vtrc_example::number* response,
                 ::google::protobuf::Closure* done)
    {
        ++server_calback_count_;
        closure_holder done_holder(done);
        std::string n(request->name( ));

        std::cout << "Server wants variable: '" << n << "'"
                  << "; thread id: " << vtrc::this_thread::get_id( ) << "\n";

        std::map<std::string, double>::const_iterator f(variables_.find(n));
        if( f == variables_.end( ) ) {
            std::cout << "Client sends exception to server...\n";
            std::ostringstream oss;
            oss << "Variable is not found: '" << n << "'";
            throw std::runtime_error( oss.str( ) );
        }
        response->set_value( f->second );
    }

public:

    variable_pool( )
        :server_calback_count_(0)
    {}

    unsigned calls_count( ) const
    {
        return server_calback_count_;
    }

    void set( std::string const &name, double value )
    {
        /// don't need lock this calls;
        variables_[name] = value;
    }

};

void tests( vtrc::shared_ptr<vtrc_client> client,
            vtrc::shared_ptr<variable_pool> vars )
{

    work_time wt;
    /// create calculator client interface
    vtrc::unique_ptr<interfaces::calculator>
                            calc(interfaces::create_calculator( client ));

    std::string test_name;
    /// first: simple sum, mul, div, pow

    std::string splitter( 80, '=' );
    splitter += "\n";

    std::cout << "My thread id: " << vtrc::this_thread::get_id( ) << "\n";

    /**
     * ======================== FIRST ==================================
    **/
    test_name = "first";
    std::cout << splitter << test_name << ":\n";
    try {

        double res = calc->mul( "pi", "e" ); /// CALL

        std::cout << "\tpi * e = " << res << "\n";
        vars->set( test_name, res ); /// now we can use old result

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== SECOND =================================
    **/
    test_name = "second";
    std::cout << splitter << test_name << ":\n";
    try {

        double res = calc->sum( 17, calc->mul( 3, 5 )); /// CALL

        std::cout << "\t17 + 3 * 5 = " << res << "\n";
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THRID ==================================
    **/
    test_name = "third";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tnow we take first and seconds results "
                  << "and make pow(firts, second)\n";

        double res = calc->pow( "first", "second" ); /// CALL

        std::cout << "\tpow(first, second) = " << res << "\n";
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THE TEST THAT FAILED ===================
    **/
    test_name = "failed";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tDivision by zero\n";

        double res = calc->div( "first", 0); /// CALL

        std::cout << "\tfirst/0 = " << res << "\n"; /// we don't see this out
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) { /// but see this
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THE TEST THAT FAILED 2 =================
    **/
    test_name = "failed2";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tRequesting invalid variabe 'invalid'"
                  << " and make 'invalid' * 1\n";

        double res = calc->mul( "invalid", 1 ); /// CALL

        std::cout << "\t'invalid' * 1 = "
                  << res << "\n"; /// we don't see this out
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) { /// but see this
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    std::cout << splitter;

    std::cout << "Total RPC was made: " << calc->calls_count( ) << "\n";

}

void on_client_ready( vtrc::condition_variable &cond )
{
    cond.notify_all( );
}

int main( int argc, char **argv ) try
{

    if( argc < 2 ) {
        usage( );
        return 1;
    }

    /// one thread for transport io, and one for calls
    pool_pair pp(1, 1);

    /// create client
    vtrc::shared_ptr<vtrc_client> client(vtrc_client::create(pp));

    /// connect slot to 'on_ready'

    client->get_on_ready( ).connect( vtrc::bind( on_client_ready,
                            vtrc::ref( ready_cond ) ) );

    /// connecting client to server
    if( argc < 3 ) {
        std::cout << "connecting to '" << argv[1] << "'...";
        client->connect( argv[1] );
        std::cout << "success\n";
    } else {
        std::cout << "connecting to '"
                  << argv[1] << ":" << argv[2] << "'...";
        client->connect( argv[1], argv[2] );
        std::cout << "success\n";
    }

    /// set rpc handler for local variable
    vtrc::shared_ptr<variable_pool> vars(vtrc::make_shared<variable_pool>());
    client->assign_weak_rpc_handler( vtrc::weak_ptr<variable_pool>(vars) );

    /// wait for client ready; There must be a better way. But anyway ... :)))
    vtrc::mutex              ready_mutex;
    vtrc::condition_variable ready_cond;
    vtrc::unique_lock<vtrc::mutex> ready_lock(ready_mutex);
    ready_cond.wait( ready_lock, vtrc::bind( &vtrc_client::ready, client ) );

    /// add some variables
    vars->set( "pi", 3.1415926 );
    vars->set( "e",  2.7182818 );

    /// we call 'tests' in another thread, for example
    vtrc::thread(tests, client, vars).join( ); /// and wait it

    std::cout << "Server callbacks count: " << vars->calls_count( ) << "\n";
    std::cout << "\n\nFINISH\n\n";

    return 0;

} catch( const std::exception &ex ) {
    std::cout << "General client error: " << ex.what( ) << "\n";
    return 2;
}
<commit_msg>examples<commit_after>#include <iostream>

#include "vtrc-client-base/vtrc-client.h"
#include "vtrc-common/vtrc-pool-pair.h"
#include "vtrc-common/vtrc-exception.h"

#include "protocol/calculator.pb.h"
#include "calculator-iface.h"

#include "vtrc-condition-variable.h"
#include "vtrc-bind.h"
#include "vtrc-ref.h"
#include "vtrc-thread.h"
#include "vtrc-chrono.h"

using namespace vtrc::client;
using namespace vtrc::common;

void usage(  )
{
    std::cout
          << "Usage: \n\tcalculator_client <server ip> <server port>\n"
          << "or:\n\tcalculator_client <localname>\n"
          << "examples:\n"
          << "\tfor tcp: calculator_client 127.0.0.1 55555\n"
          << "\tfor unix: calculator_client /tmp/calculator.sock\n"
          << "\tfor win pipe: calculator_client \\\\.\\pipe\\calculator_pipe\n";
}

struct work_time {
    typedef vtrc::chrono::high_resolution_clock::time_point time_point;
    time_point start_;
    work_time( )
        :start_(vtrc::chrono::high_resolution_clock::now( ))
    {}
    ~work_time( )
    {
        time_point::duration stop(
                    vtrc::chrono::high_resolution_clock::now( ) - start_);
        std::cout << "Call time: " << stop << "\n";
    }
};

class variable_pool: public vtrc_example::variable_pool {

    std::map<std::string, double> variables_;
    unsigned server_calback_count_;

    void set_variable(::google::protobuf::RpcController* controller,
                 const ::vtrc_example::number* request,
                 ::vtrc_example::number* response,
                 ::google::protobuf::Closure* done)
    {
        ++server_calback_count_;

        closure_holder done_holder(done);
        std::string n(request->name( ));

        std::cout << "Server sets variable: '" << n << "'"
                  << " = " <<  request->value( )
                  << " thread id: " << vtrc::this_thread::get_id( ) << "\n";

        variables_[n] = request->value( );
    }

    void get_variable(::google::protobuf::RpcController* controller,
                 const ::vtrc_example::number* request,
                 ::vtrc_example::number* response,
                 ::google::protobuf::Closure* done)
    {
        ++server_calback_count_;
        closure_holder done_holder(done);
        std::string n(request->name( ));

        std::cout << "Server wants variable: '" << n << "'"
                  << "; thread id: " << vtrc::this_thread::get_id( ) << "\n";

        std::map<std::string, double>::const_iterator f(variables_.find(n));
        if( f == variables_.end( ) ) {
            std::cout << "Client sends exception to server...\n";
            std::ostringstream oss;
            oss << "Variable is not found: '" << n << "'";
            throw std::runtime_error( oss.str( ) );
        }
        response->set_value( f->second );
    }

public:

    variable_pool( )
        :server_calback_count_(0)
    {}

    unsigned calls_count( ) const
    {
        return server_calback_count_;
    }

    void set( std::string const &name, double value )
    {
        /// don't need lock this calls;
        variables_[name] = value;
    }

};

void tests( vtrc::shared_ptr<vtrc_client> client,
            vtrc::shared_ptr<variable_pool> vars )
{

    work_time wt;
    /// create calculator client interface
    vtrc::unique_ptr<interfaces::calculator>
                            calc(interfaces::create_calculator( client ));

    std::string test_name;
    /// first: simple sum, mul, div, pow

    std::string splitter( 80, '=' );
    splitter += "\n";

    std::cout << "My thread id: " << vtrc::this_thread::get_id( ) << "\n";

    /**
     * ======================== FIRST ==================================
    **/
    test_name = "first";
    std::cout << splitter << test_name << ":\n";
    try {

        double res = calc->mul( "pi", "e" ); /// CALL

        std::cout << "\tpi * e = " << res << "\n";
        vars->set( test_name, res ); /// now we can use old result

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== SECOND =================================
    **/
    test_name = "second";
    std::cout << splitter << test_name << ":\n";
    try {

        double res = calc->sum( 17, calc->mul( 3, 5 )); /// CALL

        std::cout << "\t17 + 3 * 5 = " << res << "\n";
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THRID ==================================
    **/
    test_name = "third";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tnow we take first and seconds results "
                  << "and make pow(firts, second)\n";

        double res = calc->pow( "first", "second" ); /// CALL

        std::cout << "\tpow(first, second) = " << res << "\n";
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) {
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THE TEST THAT FAILED ===================
    **/
    test_name = "failed";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tDivision by zero\n";

        double res = calc->div( "first", 0); /// CALL

        std::cout << "\tfirst/0 = " << res << "\n"; /// we don't see this out
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) { /// but see this
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    /**
     * ======================== THE TEST THAT FAILED 2 =================
    **/
    test_name = "failed2";
    std::cout << splitter << test_name << ":\n";
    try {
        std::cout << "\tRequesting invalid variabe 'invalid'"
                  << " and make 'invalid' * 1\n";

        double res = calc->mul( "invalid", 1 ); /// CALL

        std::cout << "\t'invalid' * 1 = "
                  << res << "\n"; /// we don't see this out
        vars->set( test_name, res );

    } catch( const vtrc::common::exception& ex ) { /// but see this
        std::cout << "call '"<< test_name << "' failed: " << ex.what( ) << "; "
                  << ex.additional( ) << "\n";
    }

    std::cout << splitter;

    std::cout << "Total RPC was made: " << calc->calls_count( ) << "\n";

}

void on_client_ready( vtrc::condition_variable &cond )
{
    cond.notify_all( );
}

int main( int argc, char **argv ) try
{

    if( argc < 2 ) {
        usage( );
        return 1;
    }

    /// one thread for transport io, and one for calls
    pool_pair pp(1, 1);

    /// create client
    vtrc::shared_ptr<vtrc_client> client(vtrc_client::create(pp));

    /// connect slot to 'on_ready'
    vtrc::condition_variable ready_cond;
    client->get_on_ready( ).connect( vtrc::bind( on_client_ready,
                            vtrc::ref( ready_cond ) ) );

    /// connecting client to server
    if( argc < 3 ) {
        std::cout << "connecting to '" << argv[1] << "'...";
        client->connect( argv[1] );
        std::cout << "success\n";
    } else {
        std::cout << "connecting to '"
                  << argv[1] << ":" << argv[2] << "'...";
        client->connect( argv[1], argv[2] );
        std::cout << "success\n";
    }

    /// set rpc handler for local variable
    vtrc::shared_ptr<variable_pool> vars(vtrc::make_shared<variable_pool>());
    client->assign_weak_rpc_handler( vtrc::weak_ptr<variable_pool>(vars) );

    /// wait for client ready; There must be a better way. But anyway ... :)))
    vtrc::mutex              ready_mutex;
    vtrc::unique_lock<vtrc::mutex> ready_lock(ready_mutex);
    ready_cond.wait( ready_lock, vtrc::bind( &vtrc_client::ready, client ) );

    /// add some variables
    vars->set( "pi", 3.1415926 );
    vars->set( "e",  2.7182818 );

    /// we call 'tests' in another thread, for example
    vtrc::thread(tests, client, vars).join( ); /// and wait it

    std::cout << "Server callbacks count: " << vars->calls_count( ) << "\n";
    std::cout << "\n\nFINISH\n\n";

    return 0;

} catch( const std::exception &ex ) {
    std::cout << "General client error: " << ex.what( ) << "\n";
    return 2;
}
<|endoftext|>


<commit_before>// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#include <string.h> // memcpy

#include <nvcore/Containers.h> // nextPowerOfTwo

#include <nvcore/Memory.h>

#include "nvtt.h"
#include "InputOptions.h"

using namespace nv;
using namespace nvtt;

namespace
{

	static uint countMipmaps(int w, int h, int d)
	{
		uint mipmap = 0;

		while (w != 1 || h != 1 || d != 1) {
			w = max(1, w / 2);
			h = max(1, h / 2);
			d = max(1, d / 2);
			mipmap++;
		}

		return mipmap + 1;
	}

	// 1 -> 1, 2 -> 2, 3 -> 2, 4 -> 4, 5 -> 4, ...
	static uint previousPowerOfTwo(const uint v)
	{
		return nextPowerOfTwo(v + 1) / 2;
	}

	static uint nearestPowerOfTwo(const uint v)
	{
		const uint np2 = nextPowerOfTwo(v);
		const uint pp2 = previousPowerOfTwo(v);

		if (np2 - v <= v - pp2)
		{
			return np2;
		}
		else
		{
			return pp2;
		}
	}

} // namespace

/// Constructor.
InputOptions::InputOptions() : m(*new InputOptions::Private())
{
	reset();
}

// Delete images.
InputOptions::~InputOptions()
{
	resetTextureLayout();

	delete &m;
}

// Reset input options.
void InputOptions::reset()
{
	m.wrapMode = WrapMode_Mirror;
	m.textureType = TextureType_2D;
	m.inputFormat = InputFormat_BGRA_8UB;

	m.alphaMode = AlphaMode_Transparency;

	m.inputGamma = 2.2f;
	m.outputGamma = 2.2f;

	m.colorTransform = ColorTransform_None;
	m.linearTransform = Matrix(identity);
	for (int i = 0; i < 4; i++) m.colorOffsets[i] = 0;
	for (int i = 0; i < 4; i++) m.swizzleTransform[i] = i;

	m.generateMipmaps = true;
	m.maxLevel = -1;
	m.mipmapFilter = MipmapFilter_Box;

	m.kaiserWidth = 3;
	m.kaiserAlpha = 4.0f;
	m.kaiserStretch = 1.0f;

	m.isNormalMap = false;
	m.normalizeMipmaps = true;
	m.convertToNormalMap = false;
	m.heightFactors.set(0.0f, 0.0f, 0.0f, 1.0f);
	m.bumpFrequencyScale = Vector4(1.0f, 0.5f, 0.25f, 0.125f) / (1.0f + 0.5f + 0.25f + 0.125f);

	m.maxExtent = 0;
	m.roundMode = RoundMode_None;

	m.premultiplyAlpha = false;
}

// Setup the input image.
void InputOptions::setTextureLayout(TextureType type, int width, int height, int depth /*= 1*/)
{
	// Validate arguments.
	nvCheck(width >= 0);
	nvCheck(height >= 0);
	nvCheck(depth >= 0);

	// Correct arguments.
	if (width == 0) width = 1;
	if (height == 0) height = 1;
	if (depth == 0) depth = 1;

	// Delete previous images.
	resetTextureLayout();

	m.textureType = type;

	// Allocate images.
	m.mipmapCount = countMipmaps(width, height, depth);
	m.faceCount = (type == TextureType_Cube) ? 6 : 1;
	m.imageCount = m.mipmapCount * m.faceCount;

	m.images = new Private::InputImage[m.imageCount];

	for(uint f = 0; f < m.faceCount; f++)
	{
		uint w = width;
		uint h = height;
		uint d = depth;

		for (uint mipLevel = 0; mipLevel < m.mipmapCount; mipLevel++)
		{
			Private::InputImage & img = m.images[f * m.mipmapCount + mipLevel];
			img.width = w;
			img.height = h;
			img.depth = d;
			img.mipLevel = mipLevel;
			img.face = f;

			img.uint8data = NULL;
			img.floatdata = NULL;

			w = max(1U, w / 2);
			h = max(1U, h / 2);
			d = max(1U, d / 2);
		}
	}
}

void InputOptions::resetTextureLayout()
{
	if (m.images != NULL)
	{
		// Delete image array.
		delete [] m.images;
		m.images = NULL;

		m.faceCount = 0;
		m.mipmapCount = 0;
		m.imageCount = 0;
	}
}

// Copies the data to our internal structures.
bool InputOptions::setMipmapData(const void * data, int width, int height, int depth /*= 1*/, int face /*= 0*/, int mipLevel /*= 0*/)
{
	nvCheck(depth == 1);

	const int idx = face * m.mipmapCount + mipLevel;

	if (m.images[idx].width != width || m.images[idx].height != height || m.images[idx].depth != depth || m.images[idx].mipLevel != mipLevel || m.images[idx].face != face)
	{
		// Invalid dimension or index.
		return false;
	}

	switch(m.inputFormat)
	{
		case InputFormat_BGRA_8UB:
			if (Image * image = new nv::Image())
			{
				image->allocate(width, height);
				memcpy(image->pixels(), data, width * height * 4);
				m.images[idx].uint8data = image;
			}
			else
			{
				// @@ Out of memory error.
				return false;
			}
			break;
		case InputFormat_RGBA_32F:
			if (FloatImage * image = new nv::FloatImage())
			{
				const float * floatData = (const float *)data;
				image->allocate(4, width, height);

				for (int c = 0; c < 4; c++)
				{
					float * channel = image->channel(c);
					for (int i = 0; i < width * height; i++)
					{
						channel[i] = floatData[i*4 + c];
					}
				}

				m.images[idx].floatdata = image;
			}
			else
			{
				// @@ Out of memory error.
				return false;
			}
			break;
		default:
			return false;
	}

	return true;
}

/// Describe the format of the input.
void InputOptions::setFormat(InputFormat format)
{
	m.inputFormat = format;
}

/// Set the way the input alpha channel is interpreted.
void InputOptions::setAlphaMode(AlphaMode alphaMode)
{
	m.alphaMode = alphaMode;
}

/// Set gamma settings.
void InputOptions::setGamma(float inputGamma, float outputGamma)
{
	m.inputGamma = inputGamma;
	m.outputGamma = outputGamma;
}

/// Set texture wrappign mode.
void InputOptions::setWrapMode(WrapMode mode)
{
	m.wrapMode = mode;
}

/// Set mipmap filter.
void InputOptions::setMipmapFilter(MipmapFilter filter)
{
	m.mipmapFilter = filter;
}

/// Set mipmap generation.
void InputOptions::setMipmapGeneration(bool enabled, int maxLevel/*= -1*/)
{
	m.generateMipmaps = enabled;
	m.maxLevel = maxLevel;
}

/// Set Kaiser filter parameters.
void InputOptions::setKaiserParameters(float width, float alpha, float stretch)
{
	m.kaiserWidth = width;
	m.kaiserAlpha = alpha;
	m.kaiserStretch = stretch;
}

/// Indicate whether input is a normal map or not.
void InputOptions::setNormalMap(bool b)
{
	m.isNormalMap = b;
}

/// Enable normal map conversion.
void InputOptions::setConvertToNormalMap(bool convert)
{
	m.convertToNormalMap = convert;
}

/// Set height evaluation factors.
void InputOptions::setHeightEvaluation(float redScale, float greenScale, float blueScale, float alphaScale)
{
	// Do not normalize height factors.
//	float total = redScale + greenScale + blueScale + alphaScale;
	m.heightFactors = Vector4(redScale, greenScale, blueScale, alphaScale);
}

/// Set normal map conversion filter.
void InputOptions::setNormalFilter(float small, float medium, float big, float large)
{
	float total = small + medium + big + large;
	m.bumpFrequencyScale = Vector4(small, medium, big, large) / total;
}

/// Enable mipmap normalization.
void InputOptions::setNormalizeMipmaps(bool normalize)
{
	m.normalizeMipmaps = normalize;
}

/// Set color transform.
void InputOptions::setColorTransform(ColorTransform t)
{
	m.colorTransform = t;
}

// Set linear transform for the given channel.
void InputOptions::setLinearTransform(int channel, float w0, float w1, float w2, float w3)
{
	nvCheck(channel >= 0 && channel < 4);

	m.linearTransform(0, channel) = w0;
	m.linearTransform(1, channel) = w1;
	m.linearTransform(2, channel) = w2;
	m.linearTransform(3, channel) = w3;
}

void InputOptions::setLinearTransform(int channel, float w0, float w1, float w2, float w3, float offset)
{
	nvCheck(channel >= 0 && channel < 4);

	setLinearTransform(channel, w0, w1, w2, w3);

	m.colorOffsets[channel] = offset;
}

void InputOptions::setSwizzleTransform(int x, int y, int z, int w)
{
	nvCheck(x >= 0 && x <= 6);
	nvCheck(y >= 0 && y <= 6);
	nvCheck(z >= 0 && z <= 6);
	nvCheck(w >= 0 && w <= 6);

	m.swizzleTransform[0] = x;
	m.swizzleTransform[1] = y;
	m.swizzleTransform[2] = z;
	m.swizzleTransform[3] = w;
}

void InputOptions::setMaxExtents(int e)
{
	nvDebugCheck(e > 0);
	m.maxExtent = e;
}

void InputOptions::setRoundMode(RoundMode mode)
{
	m.roundMode = mode;
}

void InputOptions::setPremultiplyAlpha(bool b)
{
	m.premultiplyAlpha = b;
}

void InputOptions::Private::computeTargetExtents() const
{
	nvCheck(images != NULL);

	uint maxExtent = this->maxExtent;
	if (roundMode != RoundMode_None)
	{
		// rounded max extent should never be higher than original max extent.
		maxExtent = previousPowerOfTwo(maxExtent);
	}

	uint w = images->width;
	uint h = images->height;
	uint d = images->depth;

	nvDebugCheck(w > 0);
	nvDebugCheck(h > 0);
	nvDebugCheck(d > 0);

	// Scale extents without changing aspect ratio.
	uint maxwhd = max(max(w, h), d);
	if (maxExtent != 0 && maxwhd > maxExtent)
	{
		w = max((w * maxExtent) / maxwhd, 1U);
		h = max((h * maxExtent) / maxwhd, 1U);
		d = max((d * maxExtent) / maxwhd, 1U);
	}

	// Round to power of two.
	if (roundMode == RoundMode_ToNextPowerOfTwo)
	{
		w = nextPowerOfTwo(w);
		h = nextPowerOfTwo(h);
		d = nextPowerOfTwo(d);
	}
	else if (roundMode == RoundMode_ToNearestPowerOfTwo)
	{
		w = nearestPowerOfTwo(w);
		h = nearestPowerOfTwo(h);
		d = nearestPowerOfTwo(d);
	}
	else if (roundMode == RoundMode_ToPreviousPowerOfTwo)
	{
		w = previousPowerOfTwo(w);
		h = previousPowerOfTwo(h);
		d = previousPowerOfTwo(d);
	}

	this->targetWidth = w;
	this->targetHeight = h;
	this->targetDepth = d;

	this->targetMipmapCount = countMipmaps(w, h, d);
}

// Return real number of mipmaps, including first level.
// computeTargetExtents should have been called before.
int InputOptions::Private::realMipmapCount() const
{
	int mipmapCount = targetMipmapCount;

	if (!generateMipmaps) mipmapCount = 1;
	else if (maxLevel != -1 && maxLevel < mipmapCount - 1) mipmapCount = maxLevel + 1;

	return mipmapCount;
}

const Image * InputOptions::Private::image(uint face, uint mipmap) const
{
	nvDebugCheck(face < faceCount);
	nvDebugCheck(mipmap < mipmapCount);

	const InputImage & image = this->images[face * mipmapCount + mipmap];
	nvDebugCheck(image.face == face);
	nvDebugCheck(image.mipLevel == mipmap);

	return image.uint8data.ptr();
}

const Image * InputOptions::Private::image(uint idx) const
{
	nvDebugCheck(idx < faceCount * mipmapCount);

	const InputImage & image = this->images[idx];

	return image.uint8data.ptr();
}

const FloatImage * InputOptions::Private::floatImage(uint idx) const
{
	nvDebugCheck(idx < faceCount * mipmapCount);

	const InputImage & image = this->images[idx];

	return image.floatdata.ptr();
}
<commit_msg>Fix color transforms.<commit_after>// Copyright NVIDIA Corporation 2007 -- Ignacio Castano <icastano@nvidia.com>
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.

#include <string.h> // memcpy

#include <nvcore/Containers.h> // nextPowerOfTwo

#include <nvcore/Memory.h>

#include "nvtt.h"
#include "InputOptions.h"

using namespace nv;
using namespace nvtt;

namespace
{

	static uint countMipmaps(int w, int h, int d)
	{
		uint mipmap = 0;

		while (w != 1 || h != 1 || d != 1) {
			w = max(1, w / 2);
			h = max(1, h / 2);
			d = max(1, d / 2);
			mipmap++;
		}

		return mipmap + 1;
	}

	// 1 -> 1, 2 -> 2, 3 -> 2, 4 -> 4, 5 -> 4, ...
	static uint previousPowerOfTwo(const uint v)
	{
		return nextPowerOfTwo(v + 1) / 2;
	}

	static uint nearestPowerOfTwo(const uint v)
	{
		const uint np2 = nextPowerOfTwo(v);
		const uint pp2 = previousPowerOfTwo(v);

		if (np2 - v <= v - pp2)
		{
			return np2;
		}
		else
		{
			return pp2;
		}
	}

} // namespace

/// Constructor.
InputOptions::InputOptions() : m(*new InputOptions::Private())
{
	reset();
}

// Delete images.
InputOptions::~InputOptions()
{
	resetTextureLayout();

	delete &m;
}

// Reset input options.
void InputOptions::reset()
{
	m.wrapMode = WrapMode_Mirror;
	m.textureType = TextureType_2D;
	m.inputFormat = InputFormat_BGRA_8UB;

	m.alphaMode = AlphaMode_Transparency;

	m.inputGamma = 2.2f;
	m.outputGamma = 2.2f;

	m.colorTransform = ColorTransform_None;
	m.linearTransform = Matrix(identity);
	for (int i = 0; i < 4; i++) m.colorOffsets[i] = 0;
	for (int i = 0; i < 4; i++) m.swizzleTransform[i] = i;

	m.generateMipmaps = true;
	m.maxLevel = -1;
	m.mipmapFilter = MipmapFilter_Box;

	m.kaiserWidth = 3;
	m.kaiserAlpha = 4.0f;
	m.kaiserStretch = 1.0f;

	m.isNormalMap = false;
	m.normalizeMipmaps = true;
	m.convertToNormalMap = false;
	m.heightFactors.set(0.0f, 0.0f, 0.0f, 1.0f);
	m.bumpFrequencyScale = Vector4(1.0f, 0.5f, 0.25f, 0.125f) / (1.0f + 0.5f + 0.25f + 0.125f);

	m.maxExtent = 0;
	m.roundMode = RoundMode_None;

	m.premultiplyAlpha = false;
}

// Setup the input image.
void InputOptions::setTextureLayout(TextureType type, int width, int height, int depth /*= 1*/)
{
	// Validate arguments.
	nvCheck(width >= 0);
	nvCheck(height >= 0);
	nvCheck(depth >= 0);

	// Correct arguments.
	if (width == 0) width = 1;
	if (height == 0) height = 1;
	if (depth == 0) depth = 1;

	// Delete previous images.
	resetTextureLayout();

	m.textureType = type;

	// Allocate images.
	m.mipmapCount = countMipmaps(width, height, depth);
	m.faceCount = (type == TextureType_Cube) ? 6 : 1;
	m.imageCount = m.mipmapCount * m.faceCount;

	m.images = new Private::InputImage[m.imageCount];

	for(uint f = 0; f < m.faceCount; f++)
	{
		uint w = width;
		uint h = height;
		uint d = depth;

		for (uint mipLevel = 0; mipLevel < m.mipmapCount; mipLevel++)
		{
			Private::InputImage & img = m.images[f * m.mipmapCount + mipLevel];
			img.width = w;
			img.height = h;
			img.depth = d;
			img.mipLevel = mipLevel;
			img.face = f;

			img.uint8data = NULL;
			img.floatdata = NULL;

			w = max(1U, w / 2);
			h = max(1U, h / 2);
			d = max(1U, d / 2);
		}
	}
}

void InputOptions::resetTextureLayout()
{
	if (m.images != NULL)
	{
		// Delete image array.
		delete [] m.images;
		m.images = NULL;

		m.faceCount = 0;
		m.mipmapCount = 0;
		m.imageCount = 0;
	}
}

// Copies the data to our internal structures.
bool InputOptions::setMipmapData(const void * data, int width, int height, int depth /*= 1*/, int face /*= 0*/, int mipLevel /*= 0*/)
{
	nvCheck(depth == 1);

	const int idx = face * m.mipmapCount + mipLevel;

	if (m.images[idx].width != width || m.images[idx].height != height || m.images[idx].depth != depth || m.images[idx].mipLevel != mipLevel || m.images[idx].face != face)
	{
		// Invalid dimension or index.
		return false;
	}

	switch(m.inputFormat)
	{
		case InputFormat_BGRA_8UB:
			if (Image * image = new nv::Image())
			{
				image->allocate(width, height);
				memcpy(image->pixels(), data, width * height * 4);
				m.images[idx].uint8data = image;
			}
			else
			{
				// @@ Out of memory error.
				return false;
			}
			break;
		case InputFormat_RGBA_32F:
			if (FloatImage * image = new nv::FloatImage())
			{
				const float * floatData = (const float *)data;
				image->allocate(4, width, height);

				for (int c = 0; c < 4; c++)
				{
					float * channel = image->channel(c);
					for (int i = 0; i < width * height; i++)
					{
						channel[i] = floatData[i*4 + c];
					}
				}

				m.images[idx].floatdata = image;
			}
			else
			{
				// @@ Out of memory error.
				return false;
			}
			break;
		default:
			return false;
	}

	return true;
}

/// Describe the format of the input.
void InputOptions::setFormat(InputFormat format)
{
	m.inputFormat = format;
}

/// Set the way the input alpha channel is interpreted.
void InputOptions::setAlphaMode(AlphaMode alphaMode)
{
	m.alphaMode = alphaMode;
}

/// Set gamma settings.
void InputOptions::setGamma(float inputGamma, float outputGamma)
{
	m.inputGamma = inputGamma;
	m.outputGamma = outputGamma;
}

/// Set texture wrappign mode.
void InputOptions::setWrapMode(WrapMode mode)
{
	m.wrapMode = mode;
}

/// Set mipmap filter.
void InputOptions::setMipmapFilter(MipmapFilter filter)
{
	m.mipmapFilter = filter;
}

/// Set mipmap generation.
void InputOptions::setMipmapGeneration(bool enabled, int maxLevel/*= -1*/)
{
	m.generateMipmaps = enabled;
	m.maxLevel = maxLevel;
}

/// Set Kaiser filter parameters.
void InputOptions::setKaiserParameters(float width, float alpha, float stretch)
{
	m.kaiserWidth = width;
	m.kaiserAlpha = alpha;
	m.kaiserStretch = stretch;
}

/// Indicate whether input is a normal map or not.
void InputOptions::setNormalMap(bool b)
{
	m.isNormalMap = b;
}

/// Enable normal map conversion.
void InputOptions::setConvertToNormalMap(bool convert)
{
	m.convertToNormalMap = convert;
}

/// Set height evaluation factors.
void InputOptions::setHeightEvaluation(float redScale, float greenScale, float blueScale, float alphaScale)
{
	// Do not normalize height factors.
//	float total = redScale + greenScale + blueScale + alphaScale;
	m.heightFactors = Vector4(redScale, greenScale, blueScale, alphaScale);
}

/// Set normal map conversion filter.
void InputOptions::setNormalFilter(float small, float medium, float big, float large)
{
	float total = small + medium + big + large;
	m.bumpFrequencyScale = Vector4(small, medium, big, large) / total;
}

/// Enable mipmap normalization.
void InputOptions::setNormalizeMipmaps(bool normalize)
{
	m.normalizeMipmaps = normalize;
}

/// Set color transform.
void InputOptions::setColorTransform(ColorTransform t)
{
	m.colorTransform = t;
}

// Set linear transform for the given channel.
void InputOptions::setLinearTransform(int channel, float w0, float w1, float w2, float w3)
{
	nvCheck(channel >= 0 && channel < 4);

	m.linearTransform(channel, 0) = w0;
	m.linearTransform(channel, 1) = w1;
	m.linearTransform(channel, 2) = w2;
	m.linearTransform(channel, 3) = w3;
}

void InputOptions::setLinearTransform(int channel, float w0, float w1, float w2, float w3, float offset)
{
	nvCheck(channel >= 0 && channel < 4);

	setLinearTransform(channel, w0, w1, w2, w3);

	m.colorOffsets[channel] = offset;
}

void InputOptions::setSwizzleTransform(int x, int y, int z, int w)
{
	nvCheck(x >= 0 && x <= 6);
	nvCheck(y >= 0 && y <= 6);
	nvCheck(z >= 0 && z <= 6);
	nvCheck(w >= 0 && w <= 6);

	m.swizzleTransform[0] = x;
	m.swizzleTransform[1] = y;
	m.swizzleTransform[2] = z;
	m.swizzleTransform[3] = w;
}

void InputOptions::setMaxExtents(int e)
{
	nvDebugCheck(e > 0);
	m.maxExtent = e;
}

void InputOptions::setRoundMode(RoundMode mode)
{
	m.roundMode = mode;
}

void InputOptions::setPremultiplyAlpha(bool b)
{
	m.premultiplyAlpha = b;
}

void InputOptions::Private::computeTargetExtents() const
{
	nvCheck(images != NULL);

	uint maxExtent = this->maxExtent;
	if (roundMode != RoundMode_None)
	{
		// rounded max extent should never be higher than original max extent.
		maxExtent = previousPowerOfTwo(maxExtent);
	}

	uint w = images->width;
	uint h = images->height;
	uint d = images->depth;

	nvDebugCheck(w > 0);
	nvDebugCheck(h > 0);
	nvDebugCheck(d > 0);

	// Scale extents without changing aspect ratio.
	uint maxwhd = max(max(w, h), d);
	if (maxExtent != 0 && maxwhd > maxExtent)
	{
		w = max((w * maxExtent) / maxwhd, 1U);
		h = max((h * maxExtent) / maxwhd, 1U);
		d = max((d * maxExtent) / maxwhd, 1U);
	}

	// Round to power of two.
	if (roundMode == RoundMode_ToNextPowerOfTwo)
	{
		w = nextPowerOfTwo(w);
		h = nextPowerOfTwo(h);
		d = nextPowerOfTwo(d);
	}
	else if (roundMode == RoundMode_ToNearestPowerOfTwo)
	{
		w = nearestPowerOfTwo(w);
		h = nearestPowerOfTwo(h);
		d = nearestPowerOfTwo(d);
	}
	else if (roundMode == RoundMode_ToPreviousPowerOfTwo)
	{
		w = previousPowerOfTwo(w);
		h = previousPowerOfTwo(h);
		d = previousPowerOfTwo(d);
	}

	this->targetWidth = w;
	this->targetHeight = h;
	this->targetDepth = d;

	this->targetMipmapCount = countMipmaps(w, h, d);
}

// Return real number of mipmaps, including first level.
// computeTargetExtents should have been called before.
int InputOptions::Private::realMipmapCount() const
{
	int mipmapCount = targetMipmapCount;

	if (!generateMipmaps) mipmapCount = 1;
	else if (maxLevel != -1 && maxLevel < mipmapCount - 1) mipmapCount = maxLevel + 1;

	return mipmapCount;
}

const Image * InputOptions::Private::image(uint face, uint mipmap) const
{
	nvDebugCheck(face < faceCount);
	nvDebugCheck(mipmap < mipmapCount);

	const InputImage & image = this->images[face * mipmapCount + mipmap];
	nvDebugCheck(image.face == face);
	nvDebugCheck(image.mipLevel == mipmap);

	return image.uint8data.ptr();
}

const Image * InputOptions::Private::image(uint idx) const
{
	nvDebugCheck(idx < faceCount * mipmapCount);

	const InputImage & image = this->images[idx];

	return image.uint8data.ptr();
}

const FloatImage * InputOptions::Private::floatImage(uint idx) const
{
	nvDebugCheck(idx < faceCount * mipmapCount);

	const InputImage & image = this->images[idx];

	return image.floatdata.ptr();
}
<|endoftext|>


<commit_before>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2013-2020 Winlin
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef SRS_CORE_VERSION4_HPP
#define SRS_CORE_VERSION4_HPP

#define SRS_VERSION4_REVISION 64

#endif
<commit_msg>Pick from develop. 4.0.65<commit_after>/**
 * The MIT License (MIT)
 *
 * Copyright (c) 2013-2020 Winlin
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of
 * this software and associated documentation files (the "Software"), to deal in
 * the Software without restriction, including without limitation the rights to
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
 * the Software, and to permit persons to whom the Software is furnished to do so,
 * subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

#ifndef SRS_CORE_VERSION4_HPP
#define SRS_CORE_VERSION4_HPP

#define SRS_VERSION4_REVISION 65

#endif
<|endoftext|>