<commit_before>/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Initial Developer of the Original Code is
 *       Miklos Vajna <vmiklos@frugalware.org>
 * Portions created by the Initial Developer are Copyright (C) 2011 the
 * Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */

#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
#include <com/sun/star/text/WritingMode.hpp>

#include <ooxml/resourceids.hxx> // NS_ooxml namespace

#include <rtfsdrimport.hxx>

using rtl::OString;
using rtl::OStringBuffer;
using rtl::OUString;
using rtl::OUStringBuffer;
using rtl::OUStringToOString;

// NEEDSWORK: wwUtility::BGRToRGB does the same.
static sal_uInt32 lcl_BGRToRGB(sal_uInt32 nColor)
{
    sal_uInt8
        r(static_cast<sal_uInt8>(nColor&0xFF)),
        g(static_cast<sal_uInt8>(((nColor)>>8)&0xFF)),
        b(static_cast<sal_uInt8>((nColor>>16)&0xFF)),
        t(static_cast<sal_uInt8>((nColor>>24)&0xFF));
    nColor = (t<<24) + (r<<16) + (g<<8) + b;
    return nColor;
}

namespace writerfilter {
namespace rtftok {

RTFSdrImport::RTFSdrImport(RTFDocumentImpl& rDocument,
        uno::Reference<lang::XComponent> const& xDstDoc)
    : m_rImport(rDocument)
{
    uno::Reference<drawing::XDrawPageSupplier> xDrawings(xDstDoc, uno::UNO_QUERY);
    if (xDrawings.is())
        m_xDrawPage.set(xDrawings->getDrawPage(), uno::UNO_QUERY);
}

RTFSdrImport::~RTFSdrImport()
{
}

void RTFSdrImport::createShape(OUString aStr, uno::Reference<drawing::XShape>& xShape, uno::Reference<beans::XPropertySet>& xPropertySet)
{
    if (m_rImport.getModelFactory().is())
        xShape.set(m_rImport.getModelFactory()->createInstance(aStr), uno::UNO_QUERY);
    xPropertySet.set(xShape, uno::UNO_QUERY);
}

void RTFSdrImport::resolve(RTFShape& rShape)
{
    int nType = -1;
    bool bPib = false;
    bool bCustom = false;

    uno::Reference<drawing::XShape> xShape;
    uno::Reference<beans::XPropertySet> xPropertySet;
    // Create this early, as custom shapes may have properties before the type arrives.
    createShape(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CustomShape")), xShape, xPropertySet);
    uno::Any aAny;
    beans::PropertyValue aPropertyValue;
    awt::Rectangle aViewBox;
    std::vector<beans::PropertyValue> aPathPropVec;

    for (std::vector< std::pair<rtl::OUString, rtl::OUString> >::iterator i = rShape.aProperties.begin();
            i != rShape.aProperties.end(); ++i)
    {
        if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("shapeType")))
        {
            nType = i->second.toInt32();
            switch (nType)
            {
                case 20: // Line
                    createShape(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.LineShape")), xShape, xPropertySet);
                    break;
                default:
                    bCustom = true;
                    break;
            }

            // Defaults
            aAny <<= (sal_uInt32)0xffffff; // White in Word, kind of blue in Writer.
            if (xPropertySet.is())
                xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")), aAny);
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzName")))
        {
            RTFValue::Pointer_t pValue(new RTFValue(i->second));
            m_rImport.getState().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_name, pValue));
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzDescription")))
        {
            RTFValue::Pointer_t pValue(new RTFValue(i->second));
            m_rImport.getState().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_descr, pValue));
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pib")))
        {
            m_rImport.setDestinationText(i->second);
            bPib = true;
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fillColor")) && xPropertySet.is())
        {
            aAny <<= lcl_BGRToRGB(i->second.toInt32());
            xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")), aAny);
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fillBackColor")))
            ; // Ignore: complementer of fillColor
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("lineColor")) && xPropertySet.is())
        {
            aAny <<= lcl_BGRToRGB(i->second.toInt32());
            xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LineColor")), aAny);
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("lineBackColor")))
            ; // Ignore: complementer of lineColor
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("txflTextFlow")) && xPropertySet.is())
        {
            if (i->second.toInt32() == 1)
            {
                aAny <<= text::WritingMode_TB_RL;
                xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("TextWritingMode")), aAny);
            }
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fLine")) && xPropertySet.is())
        {
            if (i->second.toInt32() == 0)
            {
                aAny <<= drawing::LineStyle_NONE;
                xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LineStyle")), aAny);
            }
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pVerticies")))
        {
            uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aCoordinates;
            sal_Int32 nSize = 0; // Size of a token (it's value is hardwired in the exporter)
            sal_Int32 nCount = 0; // Number of tokens
            sal_Int32 nCharIndex = 0; // Character index
            sal_Int32 nIndex = 0; // Array index
            do
            {
                OUString aToken = i->second.getToken(0, ';', nCharIndex);
                if (!nSize)
                    nSize = aToken.toInt32();
                else if (!nCount)
                {
                    nCount = aToken.toInt32();
                    aCoordinates.realloc(nCount);
                }
                else
                {
                    // The coordinates are in an (x,y) form.
                    aToken = aToken.copy(1, aToken.getLength() - 2);
                    sal_Int32 nI = 0;
                    sal_Int32 nX = 0;
                    sal_Int32 nY = 0;
                    do
                    {
                        OUString aPoint = aToken.getToken(0, ',', nI);
                        if (!nX)
                            nX = aPoint.toInt32();
                        else
                            nY = aPoint.toInt32();
                    }
                    while (nI >= 0);
                    aCoordinates[nIndex].First.Value <<= nX;
                    aCoordinates[nIndex].Second.Value <<= nY;
                    nIndex++;
                }
            }
            while (nCharIndex >= 0);
            aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Coordinates"));
            aPropertyValue.Value <<= aCoordinates;
            aPathPropVec.push_back(aPropertyValue);
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pSegmentInfo")))
        {
            uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments;
            sal_Int32 nSize = 0;
            sal_Int32 nCount = 0;
            sal_Int32 nCharIndex = 0;
            sal_Int32 nIndex = 0;
            do
            {
                sal_Int32 nSeg = i->second.getToken(0, ';', nCharIndex).toInt32();
                if (!nSize)
                    nSize = nSeg;
                else if (!nCount)
                {
                    nCount = nSeg;
                    aSegments.realloc(nCount);
                }
                else
                {
                    switch (nSeg)
                    {
                        case 0x0001: // lineto
                            aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO;
                            aSegments[nIndex].Count = sal_Int32(1);
                            break;
                        case 0x4000: // moveto
                            aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
                            aSegments[nIndex].Count = sal_Int32(1);
                            break;
                        case 0x2001: // curveto
                            aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::CURVETO;
                            aSegments[nIndex].Count = sal_Int32(1);
                            break;
                        case 0xb300: // arcto
                            aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ARCTO;
                            aSegments[nIndex].Count = sal_Int32(0);
                            break;
                        case 0xac00:
                        case 0xaa00: // nofill
                        case 0xab00: // nostroke
                        case 0x6001: // close
                            break;
                        case 0x8000: // end
                            aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
                            aSegments[nIndex].Count = sal_Int32(0);
                            break;
                        default:
                            OSL_TRACE("%s: unhandled segment '%x' in the path", OSL_THIS_FUNC, nSeg);
                            break;
                    }
                    nIndex++;
                }
            }
            while (nCharIndex >= 0);
            aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Segments"));
            aPropertyValue.Value <<= aSegments;
            aPathPropVec.push_back(aPropertyValue);
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoLeft")))
            aViewBox.X = i->second.toInt32();
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoTop")))
            aViewBox.Y = i->second.toInt32();
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoRight")))
            aViewBox.Width = i->second.toInt32();
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoBottom")))
            aViewBox.Height = i->second.toInt32();
        else
            OSL_TRACE("%s: TODO handle shape property '%s':'%s'", OSL_THIS_FUNC,
                    OUStringToOString( i->first, RTL_TEXTENCODING_UTF8 ).getStr(),
                    OUStringToOString( i->second, RTL_TEXTENCODING_UTF8 ).getStr());
    }

    if (nType == 75 || nType == 202) // picture frame or text box
    {
        if (bPib)
            m_rImport.resolvePict(false);
        return;
    }

    if (m_xDrawPage.is())
        m_xDrawPage->add(xShape);
    if (bCustom && xShape.is())
    {
        uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY);
        xDefaulter->createCustomShapeDefaults(OUString::valueOf(sal_Int32(nType)));
    }

    // Creating Path property
    uno::Sequence<beans::PropertyValue> aPathPropSeq(aPathPropVec.size());
    beans::PropertyValue* pPathValues = aPathPropSeq.getArray();
    for (std::vector<beans::PropertyValue>::iterator i = aPathPropVec.begin(); i != aPathPropVec.end(); ++i)
        *pPathValues++ = *i;

    // Creating CustomShapeGeometry property
    std::vector<beans::PropertyValue> aGeomPropVec;
    if (aViewBox.X || aViewBox.Y || aViewBox.Width || aViewBox.Height)
    {
        aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("ViewBox"));
        aPropertyValue.Value <<= aViewBox;
        aGeomPropVec.push_back(aPropertyValue);
    }
    if (aPathPropSeq.getLength())
    {
        aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Path"));
        aPropertyValue.Value <<= aPathPropSeq;
        aGeomPropVec.push_back(aPropertyValue);
    }
    uno::Sequence<beans::PropertyValue> aGeomPropSeq(aGeomPropVec.size());
    beans::PropertyValue* pGeomValues = aGeomPropSeq.getArray();
    for (std::vector<beans::PropertyValue>::iterator i = aGeomPropVec.begin(); i != aGeomPropVec.end(); ++i)
        *pGeomValues++ = *i;
    if (aGeomPropSeq.getLength() && xPropertySet.is())
        xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("CustomShapeGeometry")), uno::Any(aGeomPropSeq));

    // Set position and size
    if (xShape.is())
    {
        xShape->setPosition(awt::Point(rShape.nLeft, rShape.nTop));
        xShape->setSize(awt::Size(rShape.nRight - rShape.nLeft, rShape.nBottom - rShape.nTop));
    }

    // Send it to dmapper
    m_rImport.Mapper().startShape(xShape);
    m_rImport.Mapper().startParagraphGroup();
    m_rImport.replayShapetext();
    m_rImport.Mapper().startCharacterGroup();
    m_rImport.runBreak();
    m_rImport.Mapper().endCharacterGroup();
    m_rImport.Mapper().endParagraphGroup();
    m_rImport.Mapper().endShape();
}

} // namespace rtftok
} // namespace writerfilter

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>no special handling of text box shapes, we already have a drawpage set<commit_after>/*
 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Initial Developer of the Original Code is
 *       Miklos Vajna <vmiklos@frugalware.org>
 * Portions created by the Initial Developer are Copyright (C) 2011 the
 * Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
 * instead of those above.
 */

#include <com/sun/star/drawing/XEnhancedCustomShapeDefaulter.hpp>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <com/sun/star/drawing/LineStyle.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
#include <com/sun/star/text/WritingMode.hpp>

#include <ooxml/resourceids.hxx> // NS_ooxml namespace

#include <rtfsdrimport.hxx>

using rtl::OString;
using rtl::OStringBuffer;
using rtl::OUString;
using rtl::OUStringBuffer;
using rtl::OUStringToOString;

// NEEDSWORK: wwUtility::BGRToRGB does the same.
static sal_uInt32 lcl_BGRToRGB(sal_uInt32 nColor)
{
    sal_uInt8
        r(static_cast<sal_uInt8>(nColor&0xFF)),
        g(static_cast<sal_uInt8>(((nColor)>>8)&0xFF)),
        b(static_cast<sal_uInt8>((nColor>>16)&0xFF)),
        t(static_cast<sal_uInt8>((nColor>>24)&0xFF));
    nColor = (t<<24) + (r<<16) + (g<<8) + b;
    return nColor;
}

namespace writerfilter {
namespace rtftok {

RTFSdrImport::RTFSdrImport(RTFDocumentImpl& rDocument,
        uno::Reference<lang::XComponent> const& xDstDoc)
    : m_rImport(rDocument)
{
    uno::Reference<drawing::XDrawPageSupplier> xDrawings(xDstDoc, uno::UNO_QUERY);
    if (xDrawings.is())
        m_xDrawPage.set(xDrawings->getDrawPage(), uno::UNO_QUERY);
}

RTFSdrImport::~RTFSdrImport()
{
}

void RTFSdrImport::createShape(OUString aStr, uno::Reference<drawing::XShape>& xShape, uno::Reference<beans::XPropertySet>& xPropertySet)
{
    if (m_rImport.getModelFactory().is())
        xShape.set(m_rImport.getModelFactory()->createInstance(aStr), uno::UNO_QUERY);
    xPropertySet.set(xShape, uno::UNO_QUERY);
}

void RTFSdrImport::resolve(RTFShape& rShape)
{
    int nType = -1;
    bool bPib = false;
    bool bCustom = false;

    uno::Reference<drawing::XShape> xShape;
    uno::Reference<beans::XPropertySet> xPropertySet;
    // Create this early, as custom shapes may have properties before the type arrives.
    createShape(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.CustomShape")), xShape, xPropertySet);
    uno::Any aAny;
    beans::PropertyValue aPropertyValue;
    awt::Rectangle aViewBox;
    std::vector<beans::PropertyValue> aPathPropVec;

    for (std::vector< std::pair<rtl::OUString, rtl::OUString> >::iterator i = rShape.aProperties.begin();
            i != rShape.aProperties.end(); ++i)
    {
        if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("shapeType")))
        {
            nType = i->second.toInt32();
            switch (nType)
            {
                case 20: // Line
                    createShape(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.drawing.LineShape")), xShape, xPropertySet);
                    break;
                default:
                    bCustom = true;
                    break;
            }

            // Defaults
            aAny <<= (sal_uInt32)0xffffff; // White in Word, kind of blue in Writer.
            if (xPropertySet.is())
                xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")), aAny);
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzName")))
        {
            RTFValue::Pointer_t pValue(new RTFValue(i->second));
            m_rImport.getState().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_name, pValue));
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("wzDescription")))
        {
            RTFValue::Pointer_t pValue(new RTFValue(i->second));
            m_rImport.getState().aCharacterAttributes->push_back(make_pair(NS_ooxml::LN_CT_NonVisualDrawingProps_descr, pValue));
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pib")))
        {
            m_rImport.setDestinationText(i->second);
            bPib = true;
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fillColor")) && xPropertySet.is())
        {
            aAny <<= lcl_BGRToRGB(i->second.toInt32());
            xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("FillColor")), aAny);
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fillBackColor")))
            ; // Ignore: complementer of fillColor
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("lineColor")) && xPropertySet.is())
        {
            aAny <<= lcl_BGRToRGB(i->second.toInt32());
            xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LineColor")), aAny);
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("lineBackColor")))
            ; // Ignore: complementer of lineColor
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("txflTextFlow")) && xPropertySet.is())
        {
            if (i->second.toInt32() == 1)
            {
                aAny <<= text::WritingMode_TB_RL;
                xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("TextWritingMode")), aAny);
            }
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("fLine")) && xPropertySet.is())
        {
            if (i->second.toInt32() == 0)
            {
                aAny <<= drawing::LineStyle_NONE;
                xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("LineStyle")), aAny);
            }
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pVerticies")))
        {
            uno::Sequence<drawing::EnhancedCustomShapeParameterPair> aCoordinates;
            sal_Int32 nSize = 0; // Size of a token (it's value is hardwired in the exporter)
            sal_Int32 nCount = 0; // Number of tokens
            sal_Int32 nCharIndex = 0; // Character index
            sal_Int32 nIndex = 0; // Array index
            do
            {
                OUString aToken = i->second.getToken(0, ';', nCharIndex);
                if (!nSize)
                    nSize = aToken.toInt32();
                else if (!nCount)
                {
                    nCount = aToken.toInt32();
                    aCoordinates.realloc(nCount);
                }
                else
                {
                    // The coordinates are in an (x,y) form.
                    aToken = aToken.copy(1, aToken.getLength() - 2);
                    sal_Int32 nI = 0;
                    sal_Int32 nX = 0;
                    sal_Int32 nY = 0;
                    do
                    {
                        OUString aPoint = aToken.getToken(0, ',', nI);
                        if (!nX)
                            nX = aPoint.toInt32();
                        else
                            nY = aPoint.toInt32();
                    }
                    while (nI >= 0);
                    aCoordinates[nIndex].First.Value <<= nX;
                    aCoordinates[nIndex].Second.Value <<= nY;
                    nIndex++;
                }
            }
            while (nCharIndex >= 0);
            aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Coordinates"));
            aPropertyValue.Value <<= aCoordinates;
            aPathPropVec.push_back(aPropertyValue);
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("pSegmentInfo")))
        {
            uno::Sequence<drawing::EnhancedCustomShapeSegment> aSegments;
            sal_Int32 nSize = 0;
            sal_Int32 nCount = 0;
            sal_Int32 nCharIndex = 0;
            sal_Int32 nIndex = 0;
            do
            {
                sal_Int32 nSeg = i->second.getToken(0, ';', nCharIndex).toInt32();
                if (!nSize)
                    nSize = nSeg;
                else if (!nCount)
                {
                    nCount = nSeg;
                    aSegments.realloc(nCount);
                }
                else
                {
                    switch (nSeg)
                    {
                        case 0x0001: // lineto
                            aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::LINETO;
                            aSegments[nIndex].Count = sal_Int32(1);
                            break;
                        case 0x4000: // moveto
                            aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::MOVETO;
                            aSegments[nIndex].Count = sal_Int32(1);
                            break;
                        case 0x2001: // curveto
                            aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::CURVETO;
                            aSegments[nIndex].Count = sal_Int32(1);
                            break;
                        case 0xb300: // arcto
                            aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ARCTO;
                            aSegments[nIndex].Count = sal_Int32(0);
                            break;
                        case 0xac00:
                        case 0xaa00: // nofill
                        case 0xab00: // nostroke
                        case 0x6001: // close
                            break;
                        case 0x8000: // end
                            aSegments[nIndex].Command = drawing::EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
                            aSegments[nIndex].Count = sal_Int32(0);
                            break;
                        default:
                            OSL_TRACE("%s: unhandled segment '%x' in the path", OSL_THIS_FUNC, nSeg);
                            break;
                    }
                    nIndex++;
                }
            }
            while (nCharIndex >= 0);
            aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Segments"));
            aPropertyValue.Value <<= aSegments;
            aPathPropVec.push_back(aPropertyValue);
        }
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoLeft")))
            aViewBox.X = i->second.toInt32();
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoTop")))
            aViewBox.Y = i->second.toInt32();
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoRight")))
            aViewBox.Width = i->second.toInt32();
        else if (i->first.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("geoBottom")))
            aViewBox.Height = i->second.toInt32();
        else
            OSL_TRACE("%s: TODO handle shape property '%s':'%s'", OSL_THIS_FUNC,
                    OUStringToOString( i->first, RTL_TEXTENCODING_UTF8 ).getStr(),
                    OUStringToOString( i->second, RTL_TEXTENCODING_UTF8 ).getStr());
    }

    if (nType == 75) // picture frame
    {
        if (bPib)
            m_rImport.resolvePict(false);
        return;
    }

    if (m_xDrawPage.is())
        m_xDrawPage->add(xShape);
    if (bCustom && xShape.is())
    {
        uno::Reference<drawing::XEnhancedCustomShapeDefaulter> xDefaulter(xShape, uno::UNO_QUERY);
        xDefaulter->createCustomShapeDefaults(OUString::valueOf(sal_Int32(nType)));
    }

    // Creating Path property
    uno::Sequence<beans::PropertyValue> aPathPropSeq(aPathPropVec.size());
    beans::PropertyValue* pPathValues = aPathPropSeq.getArray();
    for (std::vector<beans::PropertyValue>::iterator i = aPathPropVec.begin(); i != aPathPropVec.end(); ++i)
        *pPathValues++ = *i;

    // Creating CustomShapeGeometry property
    std::vector<beans::PropertyValue> aGeomPropVec;
    if (aViewBox.X || aViewBox.Y || aViewBox.Width || aViewBox.Height)
    {
        aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("ViewBox"));
        aPropertyValue.Value <<= aViewBox;
        aGeomPropVec.push_back(aPropertyValue);
    }
    if (aPathPropSeq.getLength())
    {
        aPropertyValue.Name = OUString(RTL_CONSTASCII_USTRINGPARAM("Path"));
        aPropertyValue.Value <<= aPathPropSeq;
        aGeomPropVec.push_back(aPropertyValue);
    }
    uno::Sequence<beans::PropertyValue> aGeomPropSeq(aGeomPropVec.size());
    beans::PropertyValue* pGeomValues = aGeomPropSeq.getArray();
    for (std::vector<beans::PropertyValue>::iterator i = aGeomPropVec.begin(); i != aGeomPropVec.end(); ++i)
        *pGeomValues++ = *i;
    if (aGeomPropSeq.getLength() && xPropertySet.is())
        xPropertySet->setPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("CustomShapeGeometry")), uno::Any(aGeomPropSeq));

    // Set position and size
    if (xShape.is())
    {
        xShape->setPosition(awt::Point(rShape.nLeft, rShape.nTop));
        xShape->setSize(awt::Size(rShape.nRight - rShape.nLeft, rShape.nBottom - rShape.nTop));
    }

    // Send it to dmapper
    m_rImport.Mapper().startShape(xShape);
    m_rImport.Mapper().startParagraphGroup();
    m_rImport.replayShapetext();
    m_rImport.Mapper().startCharacterGroup();
    m_rImport.runBreak();
    m_rImport.Mapper().endCharacterGroup();
    m_rImport.Mapper().endParagraphGroup();
    m_rImport.Mapper().endShape();
}

} // namespace rtftok
} // namespace writerfilter

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: SlsPageCache.cxx,v $
 *
 *  $Revision: 1.2 $
 *
 *  last change: $Author: rt $ $Date: 2004-07-13 14:10:46 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

/** All classes and template classes in this file belong to the preview
    bitmap cache.  Its tasks are the creation and caching of preview bitmaps
    for page objects.  The template class GenericPageCache is the facade
    whose specialization will be visible to the using class.  Here is a list
    of all collaborating classes.  Note that this is a work in progress.
    The division into the classes is the first step of identifiying and
    separation of the responsibilities.  Especially the choices of making a
    class a template or not was made ad hoc and will likely change.

    - BitmapCache
    The low level cache of bitmaps.  Apart from storing bitmaps and keeping
    track of how much memory they use the BitmapCache class will have the
    responsibility of destroying bitmaps when it runs out of space.

    - template <class Queue, bool UseAheadOfTimeRequests>
    class RequestFactory
    This function object class is responsible for creating requests after a
    model change when all preview bitmaps become invalid.  It can be used to
    generate ahead-of-time requests.

    - class BitmapFactory
    The static class creates preview bitmaps for page objects.

    - template<class RequestData>
    class Request
    This simple class bundles the data that are necessary for the queue to
    manage the requests.  Apart from the RequestData, typically a
    view-object-contact object, that are the priority class and the priority
    inside that class.

    - template<class RequestData>
    class RequestDataComparator
    This function object compares request objects according to their request
    data (pointer).  It is used for finding a request object that is
    associated with a given request data.

    - template<class RequestData>
    class RequestComparator
    This function object compares request objects according to their
    priority.  Objects in a lower class (0) are processed earlier then
    objects in a higher class (1).  When two objects belong to the same
    priority class they are ordered according to their priority-in-class
    value.  The function object is used to maintain the order of request
    objects in a set data structure.

    - template<class RequestData, int ClassCount>
    class GenericRequestQueue
    The request queue maintains a priority queue where each request for the
    generation of a preview bitmap has a priority that consists of two
    values: The priority class that is a rough classification that allows
    the distinction of requests for visible and for non-visible page
    objects.  The second value is the priority inside that class.

    - class QueueProcessorBase
    This class exists because the IMPL_LINK macro can not handle a template
    class.

    - template <class Queue, class RequestData, class BitmapCache,
    class BitmapFactory>
    class QueueProcessor
    The queue processor is responsible for processing the requests in the
    request queue.  In this class this is done asynchronously with a timer.
    Alternative implementations may use threads or can even process requests
    synchronously.

    - template<class RequestData,
    class CreationManager,
    class BitmapCache,
    class RequestQueue,
    class QueueProcessor>
    class GenericPageCache
    The main class in this file uses all the ones above to implement a) a cache
    and b) a factory of preview bitmaps.
*/

#include "cache/SlsPageCache.hxx"

#include "SlsBitmapCache.hxx"
#include "SlsGenericPageCache.hxx"
#include "SlsGenericRequestQueue.hxx"
#include "SlsRequestFactory.hxx"
#include "SlsCacheCompactor.hxx"
#ifdef USE_THREAD
#include "SlsQueueProcessorThread.hxx"
#else
#include "SlsQueueProcessor.hxx"
#endif
#include "SlsPreviewBitmapFactory.hxx"

using namespace ::sd::slidesorter::model;
using namespace ::sd::slidesorter::view;

namespace sd { namespace slidesorter { namespace cache {

typedef GenericRequestQueue<PageCache::RequestData,2> Queue;

#ifdef USE_THREAD
typedef QueueProcessorThread<
    Queue,
    PageCache::RequestData,
    BitmapCache,
    PreviewBitmapFactory> Processor;
#else
typedef QueueProcessor<
    Queue,
    PageCache::RequestData,
    BitmapCache,
    PreviewBitmapFactory> Processor;
#endif

typedef GenericPageCache<
    PageCache::RequestData,
    RequestFactory<Queue,false>,
    BitmapCache,
    Queue,
    CompactionByReduction,
    Processor
    > BaseClass;

class PageCache::PageCacheImplementation
    : public BaseClass
{
public:
    PageCacheImplementation (
        view::SlideSorterView& rView,
        model::SlideSorterModel& rModel,
        sal_Int32 nMaximalCacheSize)
        : BaseClass (rView,rModel, nMaximalCacheSize)
    {}
};

PageCache::PageCache (
    view::SlideSorterView& rView,
    model::SlideSorterModel& rModel,
    sal_Int32 nMaximalCacheSize)
    : mpImplementation (::std::auto_ptr<PageCacheImplementation>(
        new PageCacheImplementation(rView,rModel,nMaximalCacheSize)))
{
}

PageCache::~PageCache (void)
{
}

BitmapEx PageCache::GetPreviewBitmap (
    RequestData& rRequestData,
    const Size& rSize)
{
    return mpImplementation->GetPreviewBitmap (rRequestData, rSize);
}

void PageCache::RequestPreviewBitmap (
    RequestData& rRequestData,
    const Size& rSize)
{
    return mpImplementation->RequestPreviewBitmap (rRequestData, rSize);
}

void PageCache::InvalidatePreviewBitmap (const RequestData& rRequestData)
{
    mpImplementation->InvalidatePreviewBitmap (rRequestData);
}

void PageCache::DecreaseRequestPriority (RequestData& rRequestData)
{
    mpImplementation->DecreaseRequestPriority(rRequestData);
}

void PageCache::IncreaseRequestPriority (RequestData& rRequestData)
{
    mpImplementation->IncreaseRequestPriority(rRequestData);
}

void PageCache::ReleasePreviewBitmap (RequestData& rRequestData)
{
    mpImplementation->ReleasePreviewBitmap(rRequestData);
}

void PageCache::InvalidateCache (void)
{
    mpImplementation->InvalidateCache();
}

void PageCache::SetPreciousFlag (RequestData& rRequestData, bool bIsPrecious)
{
    mpImplementation->SetPreciousFlag (rRequestData, bIsPrecious);
}

} } } // end of namespace ::sd::slidesorter::cache
<commit_msg>INTEGRATION: CWS impress21ea (1.2.60); FILE MERGED 2004/08/26 11:16:08 af 1.2.60.1: #i32627# Using another factory for creating preview bitmaps.<commit_after>/*************************************************************************
 *
 *  $RCSfile: SlsPageCache.cxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: rt $ $Date: 2004-09-20 13:32:45 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (the "License"); You may not use this file
 *  except in compliance with the License. You may obtain a copy of the
 *  License at http://www.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

/** All classes and template classes in this file belong to the preview
    bitmap cache.  Its tasks are the creation and caching of preview bitmaps
    for page objects.  The template class GenericPageCache is the facade
    whose specialization will be visible to the using class.  Here is a list
    of all collaborating classes.  Note that this is a work in progress.
    The division into the classes is the first step of identifiying and
    separation of the responsibilities.  Especially the choices of making a
    class a template or not was made ad hoc and will likely change.

    - BitmapCache
    The low level cache of bitmaps.  Apart from storing bitmaps and keeping
    track of how much memory they use the BitmapCache class will have the
    responsibility of destroying bitmaps when it runs out of space.

    - template <class Queue, bool UseAheadOfTimeRequests>
    class RequestFactory
    This function object class is responsible for creating requests after a
    model change when all preview bitmaps become invalid.  It can be used to
    generate ahead-of-time requests.

    - class BitmapFactory
    The static class creates preview bitmaps for page objects.

    - template<class RequestData>
    class Request
    This simple class bundles the data that are necessary for the queue to
    manage the requests.  Apart from the RequestData, typically a
    view-object-contact object, that are the priority class and the priority
    inside that class.

    - template<class RequestData>
    class RequestDataComparator
    This function object compares request objects according to their request
    data (pointer).  It is used for finding a request object that is
    associated with a given request data.

    - template<class RequestData>
    class RequestComparator
    This function object compares request objects according to their
    priority.  Objects in a lower class (0) are processed earlier then
    objects in a higher class (1).  When two objects belong to the same
    priority class they are ordered according to their priority-in-class
    value.  The function object is used to maintain the order of request
    objects in a set data structure.

    - template<class RequestData, int ClassCount>
    class GenericRequestQueue
    The request queue maintains a priority queue where each request for the
    generation of a preview bitmap has a priority that consists of two
    values: The priority class that is a rough classification that allows
    the distinction of requests for visible and for non-visible page
    objects.  The second value is the priority inside that class.

    - class QueueProcessorBase
    This class exists because the IMPL_LINK macro can not handle a template
    class.

    - template <class Queue, class RequestData, class BitmapCache,
    class BitmapFactory>
    class QueueProcessor
    The queue processor is responsible for processing the requests in the
    request queue.  In this class this is done asynchronously with a timer.
    Alternative implementations may use threads or can even process requests
    synchronously.

    - template<class RequestData,
    class CreationManager,
    class BitmapCache,
    class RequestQueue,
    class QueueProcessor>
    class GenericPageCache
    The main class in this file uses all the ones above to implement a) a cache
    and b) a factory of preview bitmaps.
*/

#include "cache/SlsPageCache.hxx"
#include "SlsBitmapCache.hxx"
#include "SlsGenericPageCache.hxx"
#include "SlsGenericRequestQueue.hxx"
#include "SlsRequestFactory.hxx"
#include "SlsCacheCompactor.hxx"

// First we make some typedefs that define the arguments to the cache
// templates.  Currently there are two arguments for which exist
// alternatives:
// 1.  The queue processor is implemented once with threads and once
//     without.
#include "SlsQueueProcessor.hxx"
#define QUEUE_PROCESSOR QueueProcessor
//#include "SlsQueueProcessorThread.hxx"
//#define QUEUE_PROCESSOR QueueProcessorThread

// 2.  There are two implementations of the preview factory.  One uses the
// class PreviewRenderer (originally created for the toolpanel master page
// controls.).  The other uses the new drawing layer more directly.
#include "SlsPreviewBitmapFactory2.hxx"
#define PREVIEW_BITMAP_FACTORY PreviewBitmapFactory2
//#include "SlsPreviewBitmapFactory.hxx"
//#define PREVIEW_BITMAP_FACTORY PreviewBitmapFactory

using namespace ::sd::slidesorter::model;
using namespace ::sd::slidesorter::view;

namespace sd { namespace slidesorter { namespace cache {

typedef GenericRequestQueue<PageCache::RequestData,2> Queue;

typedef QUEUE_PROCESSOR<
    Queue,
    PageCache::RequestData,
    BitmapCache,
    PREVIEW_BITMAP_FACTORY> Processor;

typedef GenericPageCache<
    PageCache::RequestData,
    RequestFactory<Queue,false>,
    BitmapCache,
    Queue,
    CompactionByReduction,
    Processor
    > BaseClass;

class PageCache::PageCacheImplementation
    : public BaseClass
{
public:
    PageCacheImplementation (
        view::SlideSorterView& rView,
        model::SlideSorterModel& rModel,
        sal_Int32 nMaximalCacheSize)
        : BaseClass (rView,rModel, nMaximalCacheSize)
    {}
};

PageCache::PageCache (
    view::SlideSorterView& rView,
    model::SlideSorterModel& rModel,
    sal_Int32 nMaximalCacheSize)
    : mpImplementation (::std::auto_ptr<PageCacheImplementation>(
        new PageCacheImplementation(rView,rModel,nMaximalCacheSize)))
{
}

PageCache::~PageCache (void)
{
}

BitmapEx PageCache::GetPreviewBitmap (
    RequestData& rRequestData,
    const Size& rSize)
{
    return mpImplementation->GetPreviewBitmap (rRequestData, rSize);
}

void PageCache::RequestPreviewBitmap (
    RequestData& rRequestData,
    const Size& rSize)
{
    return mpImplementation->RequestPreviewBitmap (rRequestData, rSize);
}

void PageCache::InvalidatePreviewBitmap (const RequestData& rRequestData)
{
    mpImplementation->InvalidatePreviewBitmap (rRequestData);
}

void PageCache::DecreaseRequestPriority (RequestData& rRequestData)
{
    mpImplementation->DecreaseRequestPriority(rRequestData);
}

void PageCache::IncreaseRequestPriority (RequestData& rRequestData)
{
    mpImplementation->IncreaseRequestPriority(rRequestData);
}

void PageCache::ReleasePreviewBitmap (RequestData& rRequestData)
{
    mpImplementation->ReleasePreviewBitmap(rRequestData);
}

void PageCache::InvalidateCache (void)
{
    mpImplementation->InvalidateCache();
}

void PageCache::SetPreciousFlag (RequestData& rRequestData, bool bIsPrecious)
{
    mpImplementation->SetPreciousFlag (rRequestData, bIsPrecious);
}

} } } // end of namespace ::sd::slidesorter::cache
<|endoftext|>


<commit_before>// Include GLFW
#include <glfw3.h>
extern GLFWwindow* window; // The "extern" keyword here is to access the variable "window" declared in tutorialXXX.cpp. This is a hack to keep the tutorials simple. Please avoid this.

// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;

#include "controls.hpp"

glm::mat4 ViewMatrix;
glm::mat4 ProjectionMatrix;

glm::mat4 getViewMatrix(){
	return ViewMatrix;
}
glm::mat4 getProjectionMatrix(){
	return ProjectionMatrix;
}

// Initial position : on +Z
glm::vec3 position = glm::vec3( 0, 0, 5 );
// Initial horizontal angle : toward -Z
float horizontalAngle = 3.14f;
// Initial vertical angle : none
float verticalAngle = 0.0f;
// Initial Field of View
float initialFoV = 45.0f;

float speed = 3.0f; // 3 units / second
float mouseSpeed = 0.005f;

void computeMatricesFromInputs(){

	// glfwGetTime is called only once, the first time this function is called
	static double lastTime = glfwGetTime();

	// Compute time difference between current and last frame
	double currentTime = glfwGetTime();
	float deltaTime = float(currentTime - lastTime);

	// Get mouse position
	double xpos, ypos;
	glfwGetCursorPos(window, &xpos, &ypos);

	// Reset mouse position for next frame
	glfwSetCursorPos(window, 1024/2, 768/2);

	// Compute new orientation
	horizontalAngle += mouseSpeed * float(1024/2 - xpos );
	verticalAngle   += mouseSpeed * float( 768/2 - ypos );

	// Direction : Spherical coordinates to Cartesian coordinates conversion
	glm::vec3 direction(
		cos(verticalAngle) * sin(horizontalAngle),
		sin(verticalAngle),
		cos(verticalAngle) * cos(horizontalAngle)
	);

	// Right vector
	glm::vec3 right = glm::vec3(
		sin(horizontalAngle - 3.14f/2.0f),
		0,
		cos(horizontalAngle - 3.14f/2.0f)
	);

	// Up vector
	glm::vec3 up = glm::cross( right, direction );

	// Move forward
	if (glfwGetKey( window, GLFW_KEY_UP ) == GLFW_PRESS){
		position += direction * deltaTime * speed;
	}
	// Move backward
	if (glfwGetKey( window, GLFW_KEY_DOWN ) == GLFW_PRESS){
		position -= direction * deltaTime * speed;
	}
	// Strafe right
	if (glfwGetKey( window, GLFW_KEY_RIGHT ) == GLFW_PRESS){
		position += right * deltaTime * speed;
	}
	// Strafe left
	if (glfwGetKey( window, GLFW_KEY_LEFT ) == GLFW_PRESS){
		position -= right * deltaTime * speed;
	}

	float FoV = initialFoV;// - 5 * glfwGetMouseWheel(); // Now GLFW 3 requires setting up a callback for this. It's a bit too complicated for this beginner's tutorial, so it's disabled instead.

	// Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
	ProjectionMatrix = glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 100.0f);
	// Camera matrix
	ViewMatrix       = glm::lookAt(
								position,           // Camera is here
								position+direction, // and looks here : at the same position, plus "direction"
								up                  // Head is up (set to 0,-1,0 to look upside-down)
						   );

	// For the next frame, the "last time" will be "now"
	lastTime = currentTime;
}<commit_msg>Invert mouse on käytettävissä. Lisäksi koodin siivousta.<commit_after>// Include GLFW
#include <glfw3.h>
extern GLFWwindow* window; // The "extern" keyword here is to access the variable "window" declared in tutorialXXX.cpp. This is a hack to keep the tutorials simple. Please avoid this.

// Include GLM
#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;

#include "controls.hpp"

#define INVERT_MOUSE

glm::mat4 ViewMatrix;
glm::mat4 ProjectionMatrix;

glm::mat4 getViewMatrix()
{
    return ViewMatrix;
}

glm::mat4 getProjectionMatrix()
{
    return ProjectionMatrix;
}

// Initial position : on +Z
glm::vec3 position = glm::vec3(0, 0, 5);
// Initial horizontal angle : toward -Z
float horizontalAngle = 3.14f;
// Initial vertical angle : none
float verticalAngle = 0.0f;
// Initial Field of View
float initialFoV = 45.0f;

float speed = 3.0f; // 3 units / second
float mouseSpeed = 0.005f;

void computeMatricesFromInputs()
{

    // glfwGetTime is called only once, the first time this function is called
    static double lastTime = glfwGetTime();

    // Compute time difference between current and last frame
    double currentTime = glfwGetTime();
    float deltaTime = float(currentTime - lastTime);

    // Get mouse position
    double xpos, ypos;
    glfwGetCursorPos(window, &xpos, &ypos);

    // Reset mouse position for next frame
    glfwSetCursorPos(window, 1024/2, 768/2);

    // Compute new orientation
    horizontalAngle += mouseSpeed * float(1024/2 - xpos);

#ifdef INVERT_MOUSE
    // invert mouse.
    verticalAngle   -= mouseSpeed * float(768/2 - ypos);
#else
    // don't invert mouse.
    verticalAngle   += mouseSpeed * float(768/2 - ypos);
#endif

    // Direction : Spherical coordinates to Cartesian coordinates conversion
    glm::vec3 direction(
            cos(verticalAngle) * sin(horizontalAngle),
            sin(verticalAngle),
            cos(verticalAngle) * cos(horizontalAngle)
            );

    // Right vector
    glm::vec3 right = glm::vec3(
            sin(horizontalAngle - 3.14f/2.0f),
            0,
            cos(horizontalAngle - 3.14f/2.0f)
            );

    // Up vector
    glm::vec3 up = glm::cross(right, direction);

    // Move forward
    if (glfwGetKey(window, GLFW_KEY_UP) == GLFW_PRESS)
    {
        position += direction * deltaTime * speed;
    }
    // Move backward
    if (glfwGetKey(window, GLFW_KEY_DOWN) == GLFW_PRESS)
    {
        position -= direction * deltaTime * speed;
    }
    // Strafe right
    if (glfwGetKey(window, GLFW_KEY_RIGHT) == GLFW_PRESS)
    {
        position += right * deltaTime * speed;
    }
    // Strafe left
    if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS)
    {
        position -= right * deltaTime * speed;
    }

    float FoV = initialFoV;// - 5 * glfwGetMouseWheel(); // Now GLFW 3 requires setting up a callback for this. It's a bit too complicated for this beginner's tutorial, so it's disabled instead.

    // Projection matrix : 45° Field of View, 4:3 ratio, display range : 0.1 unit <-> 100 units
    ProjectionMatrix = glm::perspective(FoV, 4.0f / 3.0f, 0.1f, 100.0f);
    // Camera matrix
    ViewMatrix = glm::lookAt(
            position,           // Camera is here
            position+direction, // and looks here : at the same position, plus "direction"
            up                  // Head is up (set to 0,-1,0 to look upside-down)
            );

    // For the next frame, the "last time" will be "now"
    lastTime = currentTime;
}
<|endoftext|>


<commit_before>#ifndef REMOTEUCONTEXTIMPL_HH
# define REMOTEUCONTEXTIMPL_HH
#include <urbi/uobject.hh>
#include <urbi/usyncclient.hh>

namespace urbi
{
  namespace impl
  {
    class URBI_SDK_API RemoteUContextImpl: public impl::UContextImpl
    {
    public:
      /// Setup to work on given client
      RemoteUContextImpl(USyncClient* client);
      virtual void newUObjectClass(baseURBIStarter* s);
      virtual void newUObjectHubClass(baseURBIStarterHub* s);
      virtual void uobject_unarmorAndSend(const char* str);
      virtual void send(const char* str);
      virtual void send(const void* buf, size_t size);
      virtual void call(const std::string& object,
                        const std::string& method,
                        UAutoValue v1 = UAutoValue(),
                        UAutoValue v2 = UAutoValue(),
                        UAutoValue v3 = UAutoValue(),
                        UAutoValue v4 = UAutoValue(),
                        UAutoValue v5 = UAutoValue(),
                        UAutoValue v6 = UAutoValue(),
                        UAutoValue v7 = UAutoValue(),
                        UAutoValue v8 = UAutoValue());
      virtual UObjectMode getRunningMode();
      virtual void yield();
      virtual void yield_until(libport::utime_t deadline);
      virtual void yield_until_things_changed();
      virtual void side_effect_free_set(bool s);
      virtual bool side_effect_free_get();
      virtual UVarImpl* getVarImpl();
      virtual UObjectImpl* getObjectImpl();
      virtual UGenericCallbackImpl* getGenericCallbackImpl();
      virtual void setTimer(UTimerCallback* cb);
      virtual void registerHub(UObjectHub*);
      virtual void removeHub(UObjectHub*) ;
      virtual void setHubUpdate(UObjectHub*, ufloat);

    public:
      /// Dispatch a message on our connection
      UCallbackAction dispatcher(const UMessage& msg);
      USyncClient* getClient();
      USyncClient* client_;

#define TABLE(t, n)                                     \
    private: t n##_; public: t& n() {return n##_;}
      TABLE(UTable, accessmap);
      TABLE(UTable, eventmap);
      TABLE(UTable, eventendmap);
      TABLE(UTable, functionmap);
      TABLE(UTable, monitormap);
      TABLE(UVarTable, varmap);
      TABLE(UTimerTable, timermap);
#undef TABLE
      UTable& tableByName(const std::string& n);
      // Create it on demand.
      UObject* getDummyUObject();
      UObject* dummyUObject;
    };

    class RemoteUObjectImpl: public UObjectImpl
    {
    public:
      virtual void initialize(UObject* owner);
      virtual void clean();
      virtual void setUpdate(ufloat period);

    private:
      UObject* owner_;
      int period;
    };

    class RemoteUVarImpl: public UVarImpl
    {
    public:
      virtual void initialize(UVar* owner);
      virtual void clean();
      virtual void setOwned();
      virtual void sync();
      virtual void request();
      virtual void keepSynchronized();
      virtual void set(const UValue& v);
      virtual const UValue& get();
      virtual ufloat& in();
      virtual ufloat& out();
      virtual UDataType type();
      virtual UValue getProp(UProperty prop);
      virtual void setProp(UProperty prop, const UValue& v);
      virtual bool setBypass(bool enable);
      void update(const UValue& v);

    private:
      USyncClient* client_;
      UValue value_;
      UVar* owner_;
    };

    class RemoteUGenericCallbackImpl: public UGenericCallbackImpl
    {
    public:
      virtual void initialize(UGenericCallback* owner, bool owned);
      virtual void initialize(UGenericCallback* owner);
      virtual void registerCallback();
      virtual void clear();

    private:
      UGenericCallback* owner_;
    };
  }
}
#endif
<commit_msg>Export remote uvar impl in uobject interface.<commit_after>#ifndef REMOTEUCONTEXTIMPL_HH
# define REMOTEUCONTEXTIMPL_HH
#include <urbi/uobject.hh>
#include <urbi/usyncclient.hh>

namespace urbi
{
  namespace impl
  {
    class URBI_SDK_API RemoteUContextImpl: public impl::UContextImpl
    {
    public:
      /// Setup to work on given client
      RemoteUContextImpl(USyncClient* client);
      virtual void newUObjectClass(baseURBIStarter* s);
      virtual void newUObjectHubClass(baseURBIStarterHub* s);
      virtual void uobject_unarmorAndSend(const char* str);
      virtual void send(const char* str);
      virtual void send(const void* buf, size_t size);
      virtual void call(const std::string& object,
                        const std::string& method,
                        UAutoValue v1 = UAutoValue(),
                        UAutoValue v2 = UAutoValue(),
                        UAutoValue v3 = UAutoValue(),
                        UAutoValue v4 = UAutoValue(),
                        UAutoValue v5 = UAutoValue(),
                        UAutoValue v6 = UAutoValue(),
                        UAutoValue v7 = UAutoValue(),
                        UAutoValue v8 = UAutoValue());
      virtual UObjectMode getRunningMode();
      virtual void yield();
      virtual void yield_until(libport::utime_t deadline);
      virtual void yield_until_things_changed();
      virtual void side_effect_free_set(bool s);
      virtual bool side_effect_free_get();
      virtual UVarImpl* getVarImpl();
      virtual UObjectImpl* getObjectImpl();
      virtual UGenericCallbackImpl* getGenericCallbackImpl();
      virtual void setTimer(UTimerCallback* cb);
      virtual void registerHub(UObjectHub*);
      virtual void removeHub(UObjectHub*) ;
      virtual void setHubUpdate(UObjectHub*, ufloat);

    public:
      /// Dispatch a message on our connection
      UCallbackAction dispatcher(const UMessage& msg);
      USyncClient* getClient();
      USyncClient* client_;

#define TABLE(t, n)                                     \
    private: t n##_; public: t& n() {return n##_;}
      TABLE(UTable, accessmap);
      TABLE(UTable, eventmap);
      TABLE(UTable, eventendmap);
      TABLE(UTable, functionmap);
      TABLE(UTable, monitormap);
      TABLE(UVarTable, varmap);
      TABLE(UTimerTable, timermap);
#undef TABLE
      UTable& tableByName(const std::string& n);
      // Create it on demand.
      UObject* getDummyUObject();
      UObject* dummyUObject;
    };

    class URBI_SDK_API RemoteUObjectImpl: public UObjectImpl
    {
    public:
      virtual void initialize(UObject* owner);
      virtual void clean();
      virtual void setUpdate(ufloat period);

    private:
      UObject* owner_;
      int period;
    };

    class URBI_SDK_API RemoteUVarImpl: public UVarImpl
    {
    public:
      virtual void initialize(UVar* owner);
      virtual void clean();
      virtual void setOwned();
      virtual void sync();
      virtual void request();
      virtual void keepSynchronized();
      virtual void set(const UValue& v);
      virtual const UValue& get();
      virtual ufloat& in();
      virtual ufloat& out();
      virtual UDataType type();
      virtual UValue getProp(UProperty prop);
      virtual void setProp(UProperty prop, const UValue& v);
      virtual bool setBypass(bool enable);
      void update(const UValue& v);

    private:
      USyncClient* client_;
      UValue value_;
      UVar* owner_;
    };

    class URBI_SDK_API RemoteUGenericCallbackImpl: public UGenericCallbackImpl
    {
    public:
      virtual void initialize(UGenericCallback* owner, bool owned);
      virtual void initialize(UGenericCallback* owner);
      virtual void registerCallback();
      virtual void clear();

    private:
      UGenericCallback* owner_;
    };
  }
}
#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <string>
#include <cstring>
#include <chrono>
#include <algorithm>
#include <sstream>

#include <libsocket/unixclientstream.hpp>
#include <libsocket/exception.hpp>
#include <readline/readline.h>
#include <readline/history.h>

#include <unistd.h>
#include <stdlib.h>

#include "util.hpp"

#ifndef SDRDB_VERSION
#define SDRDB_VERSION "0.1-alpha"
#endif

#define ANSI_COLOR_RED     "\x1b[31m"
#define ANSI_COLOR_GREEN   "\x1b[32m"
#define ANSI_COLOR_YELLOW  "\x1b[33m"
#define ANSI_COLOR_BLUE    "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN    "\x1b[36m"
#define ANSI_COLOR_RESET   "\x1b[0m"

std::string bindpath { "/tmp/sdrdb.sock" };

struct help_block_arg
{
    std::string arg;
    std::string type;
    bool required;
    std::string desc;

    help_block_arg(
        const std::string & arg
      , const std::string & type
      , const bool required
      , const std::string & desc
    )
    : arg(arg)
    , type(type)
    , required(required)
    , desc(desc)
    {}

    void render() const
    {
        std::cout
            << ANSI_COLOR_YELLOW << arg << ANSI_COLOR_RESET
            << " (" << type << ") ";
        if(required) {
            std::cout << ANSI_COLOR_RED << "(required)" << ANSI_COLOR_RESET;
        }
        std::cout
            << " : "
            << desc
            << std::endl;
    }
};

struct help_block
{
    std::string cmd;
    std::string summary;
    std::vector<help_block_arg> args;
    std::vector<std::string> examples;

    help_block(
        const std::string & cmd
      , const std::string & summary
      , const std::vector<help_block_arg> & args
      , const std::vector<std::string> & examples
    )
    : cmd(cmd)
    , summary(summary)
    , args(args)
    , examples(examples)
    {}

    void render() const
    {
        std::cout << ANSI_COLOR_CYAN << cmd << ANSI_COLOR_RESET << " - " << summary << std::endl;
        for(auto & arg : args) {
            std::cout << "\t";
            arg.render();
        }

        std::cout << "EXAMPLES:" << std::endl << std::endl;

        for(auto & example : examples) {
            std::cout << example << std::endl << std::endl;
        }
    }
};

void render_help_commands_index()
{
    std::cout
        << "List of all sdrdb commands:" << std::endl
        << "Enter \"help COMMAND\" for more information" << std::endl
        << std::endl

        << "help\n\tShow this help" << std::endl
        << "exit\n\tExit interactive console" << std::endl

        << "create DBNAME AMOUNT\n\t" << std::endl
        << "drop DBNAME\n\t" << std::endl
        << "clear DBNAME\n\tEmpty database" << std::endl
        << "resize DBNAME WIDTH\n\tSet new width for database" << std::endl

        //<< "load from FILE into DBNAME\n\t" << std::endl
        //<< "save DBNAME to FILE\n\t" << std::endl

        << "put DBNAME TRAIT...\n\t" << std::endl
        << "update DBNAME CONCEPT_ID TRAIT....\n\t" << std::endl

        << "query DBNAME [WEIGHTED] similarity CONCEPT CONCEPT\n\t" << std::endl
        << "query DBNAME [WEIGHTED] usimilarity CONCEPT CONCEPT...\n\t" << std::endl
        << "query DBNAME [WEIGHTED] [ASYNC] closest AMOUNT CONCEPT\n\t" << std::endl
        << "query DBNAME matching TRAIT...\n\t" << std::endl
        << "query DBNAME [WEIGHTED] matchingx AMOUNT TRAIT...\n\t" << std::endl
        << std::endl;
}

void render_help_create()
{
    const help_block item("create", "create a new database", {
        help_block_arg("DBNAME", "string", true, "the name of the database to create"),
        help_block_arg("AMOUNT", "integer", true, "dimensions"),
    }, {
        "create newdb 1024",
        "create people 3200"
    });

    item.render();
}

void render_help_drop()
{
    const help_block item("drop", "delete a database and everything inside it", {
        help_block_arg("DBNAME", "string", true, "the name of the database to delete")
    }, {
        "drop newdb",
        "drop people"
    });

    item.render();
}

void render_help_clear()
{
    const help_block item("clear", "clear all items from database", {
        help_block_arg("DBNAME", "string", true, "the name of the database to empty")
    }, {
        "clear newdb",
        "clear people"
    });

    item.render();
}

void render_help_resize()
{
    const help_block item("resize", "change width of database", {
        help_block_arg("DBNAME", "string", true, "the name of the database to resize"),
        help_block_arg("WIDTH", "integer", true, "new dimension of database"),
    }, {
        "resize newdb 256",
        "resize people 400000"
    });

    item.render();
}

void render_help_put()
{
    const help_block item("put", "insert concept into database", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        help_block_arg("TRAIT...", "[integer]", true, "list of traits between 1 and database width"),
    }, {
        "put newdb 1 2 4 6 78 100",
        "put people 663 3393 3"
    });

    item.render();
}

void render_help_update()
{
    const help_block item("update", "change a row in database", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        help_block_arg("CONCEPT_ID", "string", true, "the concepts identifier you received from 'put'"),
        help_block_arg("TRAIT...", "[integer]", false, "same as put, if empty concept will be cleared"),
    }, {
        "update newdb 1 4 6 78",
        "update people 5 3"
    });

    item.render();
}

void render_help_query()
{
    std::cout << "try one of these:" << std::endl
        << "\thelp query similarity" << std::endl
        << "\thelp query usimilarity" << std::endl
        << "\thelp query closest" << std::endl
        << "\thelp query matching" << std::endl
        << "\thelp query matchingx" << std::endl;
}

void render_help_query_similarity()
{
    const help_block item("query similarity", "find amount of matching traits between two concepts", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        //help_block_arg("WEIGHTED", "string", false, "whether or not to use weighting data for results"),
        help_block_arg("CONCEPT_A", "integer", true, "first concept id"),
        help_block_arg("CONCEPT_B", "integer", true, "second concept id"),
    }, {
        "query newdb similarity 1 2",
        "query people similarity 5 3"
    });

    item.render();
}

void render_help_query_usimilarity()
{
    const help_block item("query usimilarity", "find amount of matching traits between concept and union of concepts", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        //help_block_arg("WEIGHTED", "string", false, "whether or not to use weighting data for results"),
        help_block_arg("CONCEPT_ID", "integer", true, "concept id to compare with"),
        help_block_arg("CONCEPT_ID...", "integer", true, "list of concept_ids OR'd with each other"),
    }, {
        "query newdb usimilarity 1 2 3 4",
        "query people usimilarity 5 3 2"
    });

    item.render();
}

void render_help_query_closest()
{
    const help_block item("query closest", "find N closest concepts to another concept", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        //help_block_arg("WEIGHTED", "string", false, "whether or not to use weighting data for results"),
        //help_block_arg("ASYNC", "string", false, "whether or not to run this asynchronously"),
        help_block_arg("AMOUNT", "integer", true, "amount to find"),
        help_block_arg("CONCEPT_ID", "integer", true, "concept to find closest to"),
    }, {
        "query newdb closest 4 2",
        "query people closest 1 3"
    });

    item.render();
}

void render_help_query_matching()
{
    const help_block item("query matching", "find concepts matching specific traits", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        //help_block_arg("WEIGHTED", "string", false, "whether or not to use weighting data for results"),
        help_block_arg("TRAITS...", "integer", true, "list of traits each concept must contain")
    }, {
        "query newdb matching 1 2",
        "query people matching 3 4"
    });

    item.render();
}

void render_help_query_matchingx()
{
    const help_block item("query matchingx", "find concepts matching at least N specific traits", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        //help_block_arg("WEIGHTED", "string", false, "whether or not to use weighting data for results"),
        help_block_arg("AMOUNT", "integer", true, "amount of traits required for inclusion"),
        help_block_arg("TRAITS...", "integer", true, "list of traits concepts must contain with respect to AMOUNT")
    }, {
        "query newdb matchingx 1 1 2",
        "query people matching 2 3 4 5"
    });

    item.render();
}

void parse_help(const std::string & str)
{
    std::istringstream iss(str);

    std::vector<std::string> pieces;

    {
        std::string piece;

        while(std::getline(iss, piece, ' ')) {
            const std::string & trimmed { trim(piece) };

            if(! trimmed.empty()) {
                pieces.push_back(piece);
            }
        }
    }

    if(pieces.size() == 2) {
        const std::string & cmd { pieces[1] };

        if(cmd == "create") {
            render_help_create();
        } else if(cmd == "drop") {
            render_help_drop();
        } else if(cmd == "clear") {
            render_help_clear();
        } else if(cmd == "resize") {
            render_help_resize();
        } else if(cmd == "put") {
            render_help_put();
        } else if(cmd == "update") {
            render_help_update();
        } else if(cmd == "query") {
            render_help_query();
        } else {
            std::cerr << "help item: " << cmd << " not found" << std::endl;
        }
    } else if(pieces.size() == 3) {
        const std::string & cmd { pieces[1] };
        if(cmd == "query") {
            const std::string & qtype { pieces[2] };

            if(qtype == "similarity") {
                render_help_query_similarity();
            } else if(qtype == "usimilarity") {
                render_help_query_usimilarity();
            } else if(qtype == "closest") {
                render_help_query_closest();
            } else if(qtype == "matching") {
                render_help_query_matching();
            } else if(qtype == "matchingx") {
                render_help_query_matchingx();
            } else {
                std::cerr << "query type: " << qtype << " not found" << std::endl;
                render_help_query();
            }
        }
    } else {
        render_help_commands_index();
    }
}

void exit_console()
{
    std::cout << "Goodbye :)" << std::endl;
}

void display_usage()
{
    std::cout
        << "Usage: sdrdb [OPTION]..." << std::endl
        << "Options and arguments:" << std::endl
        << "-h            : show this help" << std::endl
        << "-v            : show version" << std::endl
        << "-b arg        : set bindpath for server" << std::endl;
}

void display_version()
{
    std::cout << "sdrdb " << SDRDB_VERSION << std::endl;
}

void send_command(const std::string & cmd)
{
    constexpr std::size_t buffer_size { 128 };

    try {
        libsocket::unix_stream_client sock(bindpath);
        sock << cmd;

        while(true) {
            std::string answer;
            answer.resize(buffer_size);

            sock >> answer;

            std::cout << answer;

            for(char c : answer) {
                if(c == '\n') {
                    goto breaker;
                }
            }
        } breaker:;
    } catch (const libsocket::socket_exception & exc) {
        std::cerr << exc.mesg;
    }
}

bool inputloop()
{
    const char * input = readline("sdrdb" ANSI_COLOR_CYAN "> " ANSI_COLOR_RESET);

    std::string sinput(input);
    sinput = trim(sinput);

    if(sinput.length() > 0) {
        if(sinput.find("help") == 0) {
            parse_help(sinput);
        } else if(sinput == "exit") {
            exit_console();
            return false;
        } else {
            sinput += '\n';
            send_command(sinput);
        }

        add_history(input);
    }

    return true;
}

int main(int argc, char ** argv)
{
    {
        int c;

        while ((c = getopt (argc, argv, "vhb:")) != -1) {
            switch (c) {
            case 'v':
                display_version();
                return EXIT_SUCCESS;
                break;
            case 'h':
                display_usage();
                return EXIT_SUCCESS;
                break;
            case 'b':
                bindpath = optarg;
                break;
            case '?':
                std::cerr << "sdrdb-cli: invalid option" << std::endl;
                display_usage();
                return EXIT_FAILURE;
            default:
                abort ();
            }
        }
    }

    std::cout
        << "Welcome to the sdrdb interactive console. Commands end with \\n" << std::endl
        << "Server version: " << SDRDB_VERSION << std::endl
        << std::endl
        << "Type 'help' for help." << std::endl
        << std::endl;

    while(inputloop());

    return EXIT_SUCCESS;
}
<commit_msg>wording<commit_after>#include <iostream>
#include <string>
#include <cstring>
#include <chrono>
#include <algorithm>
#include <sstream>

#include <libsocket/unixclientstream.hpp>
#include <libsocket/exception.hpp>
#include <readline/readline.h>
#include <readline/history.h>

#include <unistd.h>
#include <stdlib.h>

#include "util.hpp"

#ifndef SDRDB_VERSION
#define SDRDB_VERSION "0.1-alpha"
#endif

#define ANSI_COLOR_RED     "\x1b[31m"
#define ANSI_COLOR_GREEN   "\x1b[32m"
#define ANSI_COLOR_YELLOW  "\x1b[33m"
#define ANSI_COLOR_BLUE    "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN    "\x1b[36m"
#define ANSI_COLOR_RESET   "\x1b[0m"

std::string bindpath { "/tmp/sdrdb.sock" };

struct help_block_arg
{
    std::string arg;
    std::string type;
    bool required;
    std::string desc;

    help_block_arg(
        const std::string & arg
      , const std::string & type
      , const bool required
      , const std::string & desc
    )
    : arg(arg)
    , type(type)
    , required(required)
    , desc(desc)
    {}

    void render() const
    {
        std::cout
            << ANSI_COLOR_YELLOW << arg << ANSI_COLOR_RESET
            << " (" << type << ") ";
        if(required) {
            std::cout << ANSI_COLOR_RED << "(required)" << ANSI_COLOR_RESET;
        }
        std::cout
            << " : "
            << desc
            << std::endl;
    }
};

struct help_block
{
    std::string cmd;
    std::string summary;
    std::vector<help_block_arg> args;
    std::vector<std::string> examples;

    help_block(
        const std::string & cmd
      , const std::string & summary
      , const std::vector<help_block_arg> & args
      , const std::vector<std::string> & examples
    )
    : cmd(cmd)
    , summary(summary)
    , args(args)
    , examples(examples)
    {}

    void render() const
    {
        std::cout << ANSI_COLOR_CYAN << cmd << ANSI_COLOR_RESET << " - " << summary << std::endl;
        for(auto & arg : args) {
            std::cout << "\t";
            arg.render();
        }

        std::cout << "EXAMPLES:" << std::endl << std::endl;

        for(auto & example : examples) {
            std::cout << example << std::endl << std::endl;
        }
    }
};

void render_help_commands_index()
{
    std::cout
        << "List of all sdrdb commands:" << std::endl
        << "Enter \"help COMMAND\" for more information" << std::endl
        << std::endl

        << "help\n\tShow this help" << std::endl
        << "exit\n\tExit interactive console" << std::endl

        << "create DBNAME AMOUNT\n\t" << std::endl
        << "drop DBNAME\n\t" << std::endl
        << "clear DBNAME\n\tEmpty database" << std::endl
        << "resize DBNAME WIDTH\n\tSet new width for database" << std::endl

        //<< "load from FILE into DBNAME\n\t" << std::endl
        //<< "save DBNAME to FILE\n\t" << std::endl

        << "put DBNAME TRAIT...\n\t" << std::endl
        << "update DBNAME CONCEPT_ID TRAIT....\n\t" << std::endl

        << "query DBNAME [WEIGHTED] similarity CONCEPT CONCEPT\n\t" << std::endl
        << "query DBNAME [WEIGHTED] usimilarity CONCEPT CONCEPT...\n\t" << std::endl
        << "query DBNAME [WEIGHTED] [ASYNC] closest AMOUNT CONCEPT\n\t" << std::endl
        << "query DBNAME matching TRAIT...\n\t" << std::endl
        << "query DBNAME [WEIGHTED] matchingx AMOUNT TRAIT...\n\t" << std::endl
        << std::endl;
}

void render_help_create()
{
    const help_block item("create", "create a new database", {
        help_block_arg("DBNAME", "string", true, "the name of the database to create"),
        help_block_arg("AMOUNT", "integer", true, "dimensions"),
    }, {
        "create newdb 1024",
        "create people 3200"
    });

    item.render();
}

void render_help_drop()
{
    const help_block item("drop", "delete a database and everything inside it", {
        help_block_arg("DBNAME", "string", true, "the name of the database to delete")
    }, {
        "drop newdb",
        "drop people"
    });

    item.render();
}

void render_help_clear()
{
    const help_block item("clear", "clear all items from database", {
        help_block_arg("DBNAME", "string", true, "the name of the database to empty")
    }, {
        "clear newdb",
        "clear people"
    });

    item.render();
}

void render_help_resize()
{
    const help_block item("resize", "change width of database", {
        help_block_arg("DBNAME", "string", true, "the name of the database to resize"),
        help_block_arg("WIDTH", "integer", true, "new dimension of database"),
    }, {
        "resize newdb 256",
        "resize people 400000"
    });

    item.render();
}

void render_help_put()
{
    const help_block item("put", "insert concept into database", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        help_block_arg("TRAIT...", "[integer]", true, "list of traits between 1 and database width"),
    }, {
        "put newdb 1 2 4 6 78 100",
        "put people 663 3393 3"
    });

    item.render();
}

void render_help_update()
{
    const help_block item("update", "change a row in database", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        help_block_arg("CONCEPT_ID", "string", true, "the concepts identifier you received from 'put'"),
        help_block_arg("TRAIT...", "[integer]", false, "same as put, if empty concept will be cleared"),
    }, {
        "update newdb 1 4 6 78",
        "update people 5 3"
    });

    item.render();
}

void render_help_query()
{
    std::cout << "try one of these:" << std::endl
        << "\thelp query similarity" << std::endl
        << "\thelp query usimilarity" << std::endl
        << "\thelp query closest" << std::endl
        << "\thelp query matching" << std::endl
        << "\thelp query matchingx" << std::endl;
}

void render_help_query_similarity()
{
    const help_block item("query similarity", "find amount of matching traits between two concepts", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        //help_block_arg("WEIGHTED", "string", false, "whether or not to use weighting data for results"),
        help_block_arg("CONCEPT_A", "integer", true, "first concept id"),
        help_block_arg("CONCEPT_B", "integer", true, "second concept id"),
    }, {
        "query newdb similarity 1 2",
        "query people similarity 5 3"
    });

    item.render();
}

void render_help_query_usimilarity()
{
    const help_block item("query usimilarity", "find amount of matching traits between concept and union of concepts", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        //help_block_arg("WEIGHTED", "string", false, "whether or not to use weighting data for results"),
        help_block_arg("CONCEPT_ID", "integer", true, "concept id to compare with"),
        help_block_arg("CONCEPT_ID...", "integer", true, "list of concept_ids OR'd with each other"),
    }, {
        "query newdb usimilarity 1 2 3 4",
        "query people usimilarity 5 3 2"
    });

    item.render();
}

void render_help_query_closest()
{
    const help_block item("query closest", "find N closest concepts to another concept", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        //help_block_arg("WEIGHTED", "string", false, "whether or not to use weighting data for results"),
        //help_block_arg("ASYNC", "string", false, "whether or not to run this asynchronously"),
        help_block_arg("AMOUNT", "integer", true, "amount to find"),
        help_block_arg("CONCEPT_ID", "integer", true, "concept to find closest to"),
    }, {
        "query newdb closest 4 2",
        "query people closest 1 3"
    });

    item.render();
}

void render_help_query_matching()
{
    const help_block item("query matching", "find concepts matching specific traits", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        //help_block_arg("WEIGHTED", "string", false, "whether or not to use weighting data for results"),
        help_block_arg("TRAITS...", "integer", true, "list of traits each concept must contain")
    }, {
        "query newdb matching 1 2",
        "query people matching 3 4"
    });

    item.render();
}

void render_help_query_matchingx()
{
    const help_block item("query matchingx", "find concepts matching at least N specific traits", {
        help_block_arg("DBNAME", "string", true, "the name of the database"),
        //help_block_arg("WEIGHTED", "string", false, "whether or not to use weighting data for results"),
        help_block_arg("AMOUNT", "integer", true, "amount of traits required for inclusion"),
        help_block_arg("TRAITS...", "integer", true, "list of traits concepts must contain with respect to AMOUNT")
    }, {
        "query newdb matchingx 1 1 2",
        "query people matching 2 3 4 5"
    });

    item.render();
}

void parse_help(const std::string & str)
{
    std::istringstream iss(str);

    std::vector<std::string> pieces;

    {
        std::string piece;

        while(std::getline(iss, piece, ' ')) {
            const std::string & trimmed { trim(piece) };

            if(! trimmed.empty()) {
                pieces.push_back(piece);
            }
        }
    }

    if(pieces.size() == 2) {
        const std::string & cmd { pieces[1] };

        if(cmd == "create") {
            render_help_create();
        } else if(cmd == "drop") {
            render_help_drop();
        } else if(cmd == "clear") {
            render_help_clear();
        } else if(cmd == "resize") {
            render_help_resize();
        } else if(cmd == "put") {
            render_help_put();
        } else if(cmd == "update") {
            render_help_update();
        } else if(cmd == "query") {
            render_help_query();
        } else {
            std::cerr << "help item: " << cmd << " not found" << std::endl;
        }
    } else if(pieces.size() == 3) {
        const std::string & cmd { pieces[1] };
        if(cmd == "query") {
            const std::string & qtype { pieces[2] };

            if(qtype == "similarity") {
                render_help_query_similarity();
            } else if(qtype == "usimilarity") {
                render_help_query_usimilarity();
            } else if(qtype == "closest") {
                render_help_query_closest();
            } else if(qtype == "matching") {
                render_help_query_matching();
            } else if(qtype == "matchingx") {
                render_help_query_matchingx();
            } else {
                std::cerr << "query type: " << qtype << " not found" << std::endl;
                render_help_query();
            }
        }
    } else {
        render_help_commands_index();
    }
}

void exit_console()
{
    std::cout << "Goodbye :)" << std::endl;
}

void display_usage()
{
    std::cout
        << "Usage: sdrdb-cli [OPTION]..." << std::endl
        << "Options and arguments:" << std::endl
        << "-h            : show this help" << std::endl
        << "-v            : show version" << std::endl
        << "-b arg        : set bindpath for server" << std::endl;
}

void display_version()
{
    std::cout << "sdrdb " << SDRDB_VERSION << std::endl;
}

void send_command(const std::string & cmd)
{
    constexpr std::size_t buffer_size { 128 };

    try {
        libsocket::unix_stream_client sock(bindpath);
        sock << cmd;

        while(true) {
            std::string answer;
            answer.resize(buffer_size);

            sock >> answer;

            std::cout << answer;

            for(char c : answer) {
                if(c == '\n') {
                    goto breaker;
                }
            }
        } breaker:;
    } catch (const libsocket::socket_exception & exc) {
        std::cerr << exc.mesg;
    }
}

bool inputloop()
{
    const char * input = readline("sdrdb" ANSI_COLOR_CYAN "> " ANSI_COLOR_RESET);

    std::string sinput(input);
    sinput = trim(sinput);

    if(sinput.length() > 0) {
        if(sinput.find("help") == 0) {
            parse_help(sinput);
        } else if(sinput == "exit") {
            exit_console();
            return false;
        } else {
            sinput += '\n';
            send_command(sinput);
        }

        add_history(input);
    }

    return true;
}

int main(int argc, char ** argv)
{
    {
        int c;

        while ((c = getopt (argc, argv, "vhb:")) != -1) {
            switch (c) {
            case 'v':
                display_version();
                return EXIT_SUCCESS;
                break;
            case 'h':
                display_usage();
                return EXIT_SUCCESS;
                break;
            case 'b':
                bindpath = optarg;
                break;
            case '?':
                std::cerr << "sdrdb-cli: invalid option" << std::endl;
                display_usage();
                return EXIT_FAILURE;
            default:
                abort ();
            }
        }
    }

    std::cout
        << "Welcome to the sdrdb interactive console." << std::endl
        << "Version: " << SDRDB_VERSION << std::endl
        << std::endl
        << "Type 'help' for help." << std::endl
        << std::endl;

    while(inputloop());

    return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include "compiler/prepare_grammar/extract_tokens.h"
#include <map>
#include <vector>
#include <set>
#include <string>
#include "tree_sitter/compiler.h"
#include "compiler/prepared_grammar.h"
#include "compiler/rules/visitor.h"
#include "compiler/rules/symbol.h"
#include "compiler/rules/string.h"
#include "compiler/rules/metadata.h"
#include "compiler/rules/pattern.h"
#include "compiler/prepare_grammar/token_description.h"
#include "compiler/prepare_grammar/is_token.h"

namespace tree_sitter {
namespace prepare_grammar {

using std::pair;
using std::tuple;
using std::string;
using std::map;
using std::to_string;
using std::vector;
using std::set;
using std::make_shared;
using std::dynamic_pointer_cast;
using rules::rule_ptr;
using rules::Symbol;
using rules::SymbolOptionToken;
using rules::SymbolOptionAuxToken;

class UsedSymbols : public rules::IdentityRuleFn {
  set<Symbol> used_symbols_;

  rules::rule_ptr apply(rules::Symbol *sym) {
    used_symbols_.insert(*sym);
    return sym->copy();
  }
};

class SymbolInliner : public rules::IdentityRuleFn {
  map<Symbol, Symbol> replacements;
  using rules::IdentityRuleFn::apply_to;

  int new_index_for_symbol(const Symbol &symbol) {
    int result = symbol.index;
    for (const auto &pair : replacements)
      if (pair.first.index < symbol.index &&
          pair.first.is_auxiliary() == symbol.is_auxiliary())
        result--;
    return result;
  }

  rule_ptr apply_to(const Symbol *rule) { return replace_symbol(*rule).copy(); }

 public:
  Symbol replace_symbol(const Symbol &rule) {
    if (rule.is_built_in())
      return rule;
    auto replacement_pair = replacements.find(rule);
    if (replacement_pair != replacements.end())
      return replacement_pair->second;
    else
      return Symbol(new_index_for_symbol(rule), rule.options);
  }

  explicit SymbolInliner(const map<Symbol, Symbol> &replacements)
      : replacements(replacements) {}
};

class TokenExtractor : public rules::IdentityRuleFn {

  rule_ptr apply_to_token(const rules::Rule *input) {
    auto rule = input->copy();
    for (size_t i = 0; i < tokens.size(); i++)
      if (tokens[i].second->operator==(*rule))
        return make_shared<Symbol>(i, SymbolOptionAuxToken);
    size_t index = tokens.size();
    tokens.push_back({ token_description(rule), rule });
    return make_shared<Symbol>(index, SymbolOptionAuxToken);
  }

  rule_ptr default_apply(const rules::Rule *rule) {
    auto result = rule->copy();
    if (is_token(rule->copy())) {
      return apply_to_token(rule);
    } else {
      return result;
    }
  }

  rule_ptr apply_to(const rules::Metadata *rule) {
    auto result = rule->copy();
    if (is_token(rule->copy())) {
      return apply_to_token(rule);
    } else {
      return rules::IdentityRuleFn::apply_to(rule);
    }
  }

 public:
  vector<pair<string, rule_ptr>> tokens;
};

static const GrammarError *ubiq_token_err(const string &msg) {
  return new GrammarError(GrammarErrorTypeInvalidUbiquitousToken, msg);
}

tuple<SyntaxGrammar, LexicalGrammar, const GrammarError *> extract_tokens(
    const Grammar &grammar) {
  vector<pair<string, rule_ptr>> rules, tokens, aux_rules, aux_tokens;
  vector<rule_ptr> separators;
  set<Symbol> ubiquitous_tokens;
  map<Symbol, Symbol> symbol_replacements;

  TokenExtractor extractor;

  for (size_t i = 0; i < grammar.rules().size(); i++) {
    auto pair = grammar.rules()[i];
    if (is_token(pair.second)) {
      tokens.push_back(pair);
      symbol_replacements.insert(
          { Symbol(i), Symbol(tokens.size() - 1, SymbolOptionToken) });
    } else {
      rules.push_back({ pair.first, extractor.apply(pair.second) });
    }
  }

  aux_tokens.insert(aux_tokens.end(), extractor.tokens.begin(),
                    extractor.tokens.end());

  SymbolInliner inliner(symbol_replacements);
  for (auto &pair : rules)
    pair.second = inliner.apply(pair.second);

  for (auto rule : grammar.ubiquitous_tokens()) {
    if (is_token(rule)) {
      separators.push_back(rule);
    } else {
      auto sym = dynamic_pointer_cast<const Symbol>(extractor.apply(rule));
      if (!sym.get())
        return { SyntaxGrammar(), LexicalGrammar(),
                 ubiq_token_err("Not a token: " + rule->to_string()) };

      Symbol symbol = inliner.replace_symbol(*sym);
      if (!symbol.is_token())
        return { SyntaxGrammar(), LexicalGrammar(),
                 ubiq_token_err("Not a token: " + symbol.to_string()) };

      ubiquitous_tokens.insert(symbol);
    }
  }

  return { SyntaxGrammar(rules, aux_rules, ubiquitous_tokens),
           LexicalGrammar(tokens, aux_tokens, separators), nullptr };
}

}  // namespace prepare_grammar
}  // namespace tree_sitter
<commit_msg>Use make_tuple rather than init list syntax for gcc<commit_after>#include "compiler/prepare_grammar/extract_tokens.h"
#include <map>
#include <vector>
#include <set>
#include <string>
#include "tree_sitter/compiler.h"
#include "compiler/prepared_grammar.h"
#include "compiler/rules/visitor.h"
#include "compiler/rules/symbol.h"
#include "compiler/rules/string.h"
#include "compiler/rules/metadata.h"
#include "compiler/rules/pattern.h"
#include "compiler/prepare_grammar/token_description.h"
#include "compiler/prepare_grammar/is_token.h"

namespace tree_sitter {
namespace prepare_grammar {

using std::pair;
using std::tuple;
using std::string;
using std::map;
using std::to_string;
using std::vector;
using std::set;
using std::make_shared;
using std::make_tuple;
using std::dynamic_pointer_cast;
using rules::rule_ptr;
using rules::Symbol;
using rules::SymbolOptionToken;
using rules::SymbolOptionAuxToken;

class UsedSymbols : public rules::IdentityRuleFn {
  set<Symbol> used_symbols_;

  rules::rule_ptr apply(rules::Symbol *sym) {
    used_symbols_.insert(*sym);
    return sym->copy();
  }
};

class SymbolInliner : public rules::IdentityRuleFn {
  map<Symbol, Symbol> replacements;
  using rules::IdentityRuleFn::apply_to;

  int new_index_for_symbol(const Symbol &symbol) {
    int result = symbol.index;
    for (const auto &pair : replacements)
      if (pair.first.index < symbol.index &&
          pair.first.is_auxiliary() == symbol.is_auxiliary())
        result--;
    return result;
  }

  rule_ptr apply_to(const Symbol *rule) { return replace_symbol(*rule).copy(); }

 public:
  Symbol replace_symbol(const Symbol &rule) {
    if (rule.is_built_in())
      return rule;
    auto replacement_pair = replacements.find(rule);
    if (replacement_pair != replacements.end())
      return replacement_pair->second;
    else
      return Symbol(new_index_for_symbol(rule), rule.options);
  }

  explicit SymbolInliner(const map<Symbol, Symbol> &replacements)
      : replacements(replacements) {}
};

class TokenExtractor : public rules::IdentityRuleFn {

  rule_ptr apply_to_token(const rules::Rule *input) {
    auto rule = input->copy();
    for (size_t i = 0; i < tokens.size(); i++)
      if (tokens[i].second->operator==(*rule))
        return make_shared<Symbol>(i, SymbolOptionAuxToken);
    size_t index = tokens.size();
    tokens.push_back({ token_description(rule), rule });
    return make_shared<Symbol>(index, SymbolOptionAuxToken);
  }

  rule_ptr default_apply(const rules::Rule *rule) {
    auto result = rule->copy();
    if (is_token(rule->copy())) {
      return apply_to_token(rule);
    } else {
      return result;
    }
  }

  rule_ptr apply_to(const rules::Metadata *rule) {
    auto result = rule->copy();
    if (is_token(rule->copy())) {
      return apply_to_token(rule);
    } else {
      return rules::IdentityRuleFn::apply_to(rule);
    }
  }

 public:
  vector<pair<string, rule_ptr>> tokens;
};

static const GrammarError *ubiq_token_err(const string &msg) {
  return new GrammarError(GrammarErrorTypeInvalidUbiquitousToken, msg);
}

tuple<SyntaxGrammar, LexicalGrammar, const GrammarError *> extract_tokens(
    const Grammar &grammar) {
  vector<pair<string, rule_ptr>> rules, tokens, aux_rules, aux_tokens;
  vector<rule_ptr> separators;
  set<Symbol> ubiquitous_tokens;
  map<Symbol, Symbol> symbol_replacements;

  TokenExtractor extractor;

  for (size_t i = 0; i < grammar.rules().size(); i++) {
    auto pair = grammar.rules()[i];
    if (is_token(pair.second)) {
      tokens.push_back(pair);
      symbol_replacements.insert(
          { Symbol(i), Symbol(tokens.size() - 1, SymbolOptionToken) });
    } else {
      rules.push_back({ pair.first, extractor.apply(pair.second) });
    }
  }

  aux_tokens.insert(aux_tokens.end(), extractor.tokens.begin(),
                    extractor.tokens.end());

  SymbolInliner inliner(symbol_replacements);
  for (auto &pair : rules)
    pair.second = inliner.apply(pair.second);

  for (auto rule : grammar.ubiquitous_tokens()) {
    if (is_token(rule)) {
      separators.push_back(rule);
    } else {
      auto sym = dynamic_pointer_cast<const Symbol>(extractor.apply(rule));
      if (!sym.get())
        return make_tuple(SyntaxGrammar(), LexicalGrammar(),
                 ubiq_token_err("Not a token: " + rule->to_string()));

      Symbol symbol = inliner.replace_symbol(*sym);
      if (!symbol.is_token())
        return make_tuple(SyntaxGrammar(), LexicalGrammar(),
                 ubiq_token_err("Not a token: " + symbol.to_string()));

      ubiquitous_tokens.insert(symbol);
    }
  }

  return make_tuple(SyntaxGrammar(rules, aux_rules, ubiquitous_tokens),
           LexicalGrammar(tokens, aux_tokens, separators), nullptr);
}

}  // namespace prepare_grammar
}  // namespace tree_sitter
<|endoftext|>