<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "Util.hxx"

#include <rtl/ustrbuf.hxx>

using namespace ::connectivity;

using namespace ::rtl;

using namespace ::com::sun::star;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::uno;

OUString firebird::sanitizeIdentifier(const OUString& rIdentifier)
{
    OUString sRet = rIdentifier.trim();
    assert(sRet.getLength() <= 31); // Firebird identifiers cannot be longer than this.

    return sRet;
}

void firebird::evaluateStatusVector(ISC_STATUS_ARRAY& aStatusVector,
                                    const OUString& aCause,
                                    const uno::Reference< XInterface >& _rxContext)
    throw(SQLException)
{
    if (aStatusVector[0]==1 && aStatusVector[1]) // indicates error
    {
        OUStringBuffer buf;
        char msg[512]; // Size is based on suggestion in docs.
        const ISC_STATUS* pStatus = (const ISC_STATUS*) &aStatusVector;

        buf.appendAscii("firebird_sdbc error:");
        while(fb_interpret(msg, sizeof(msg), &pStatus))
        {
            // TODO: verify encoding
            buf.appendAscii("\n*");
            buf.append(OUString(msg, strlen(msg), RTL_TEXTENCODING_UTF8));
        }
        buf.appendAscii("\ncaused by\n'").append(aCause).appendAscii("'\n");

        OUString error = buf.makeStringAndClear();
        SAL_WARN("connectivity.firebird", error);

        throw SQLException( error, _rxContext, OUString(), 1, Any() );
    }
}

sal_Int32 firebird::getColumnTypeFromFBType(short aType)
{
    aType &= ~1; // Remove last bit -- it is used to denote whether column
                 // can store Null, not needed for type determination
    switch (aType)
    {
    case SQL_TEXT:
        return DataType::CHAR;
    case SQL_VARYING:
        return DataType::VARCHAR;
    case SQL_SHORT:
        return DataType::SMALLINT;
    case SQL_LONG:
        return DataType::INTEGER;
    case SQL_FLOAT:
        return DataType::FLOAT;
    case SQL_DOUBLE:
        return DataType::DOUBLE;
    case SQL_D_FLOAT:
        return DataType::DOUBLE;
    case SQL_TIMESTAMP:
        return DataType::TIMESTAMP;
    case SQL_BLOB:
        return DataType::BLOB;
    case SQL_ARRAY:
        return DataType::ARRAY;
    case SQL_TYPE_TIME:
        return DataType::TIME;
    case SQL_TYPE_DATE:
        return DataType::DATE;
    case SQL_INT64:
        return DataType::BIGINT;
    case SQL_NULL:
        return DataType::SQLNULL;
    case SQL_QUAD:      // Is a "Blob ID" according to the docs
        return 0;       // TODO: verify
    default:
        assert(false); // Should never happen
        return 0;
    }
}

OUString firebird::getColumnTypeNameFromFBType(short aType)
{
    aType &= ~1; // Remove last bit -- it is used to denote whether column
                // can store Null, not needed for type determination
    switch (aType)
    {
    case SQL_TEXT:
        return OUString("SQL_TEXT");
    case SQL_VARYING:
        return OUString("SQL_VARYING");
    case SQL_SHORT:
        return OUString("SQL_SHORT");
    case SQL_LONG:
        return OUString("SQL_LONG");
    case SQL_FLOAT:
        return OUString("SQL_FLOAT");
    case SQL_DOUBLE:
        return OUString("SQL_DOUBLE");
    case SQL_D_FLOAT:
        return OUString("SQL_D_FLOAT");
    case SQL_TIMESTAMP:
        return OUString("SQL_TIMESTAMP");
    case SQL_BLOB:
        return OUString("SQL_BLOB");
    case SQL_ARRAY:
        return OUString("SQL_ARRAY");
    case SQL_TYPE_TIME:
        return OUString("SQL_TYPE_TIME");
    case SQL_TYPE_DATE:
        return OUString("SQL_TYPE_DATE");
    case SQL_INT64:
        return OUString("SQL_INT64");
    case SQL_NULL:
        return OUString("SQL_NULL");
    case SQL_QUAD:
        return OUString("SQL_QUAD");
    default:
        assert(false); // Should never happen
        return OUString();
    }
}

short firebird::getFBTypeFromBlrType(short blrType)
{
    switch (blrType)
    {
    case blr_text:
        return SQL_TEXT;
    case blr_text2:
        assert(false);
        return 0; // No idea if this should be supported
    case blr_varying:
        return SQL_VARYING;
    case blr_varying2:
        assert(false);
        return 0; // No idea if this should be supported
    case blr_short:
        return SQL_SHORT;
    case blr_long:
        return SQL_LONG;
    case blr_float:
        return SQL_FLOAT;
    case blr_double:
        return SQL_DOUBLE;
    case blr_d_float:
        return SQL_D_FLOAT;
    case blr_timestamp:
        return SQL_TIMESTAMP;
    case blr_blob:
        return SQL_BLOB;
//     case blr_SQL_ARRAY:
//         return OUString("SQL_ARRAY");
    case blr_sql_time:
        return SQL_TYPE_TIME;
    case blr_sql_date:
        return SQL_TYPE_DATE;
    case blr_int64:
        return SQL_INT64;
//     case SQL_NULL:
//         return OUString("SQL_NULL");
    case blr_quad:
        return SQL_QUAD;
    default:
        // If this happens we have hit one of the extra types in ibase.h
        // look up blr_* for a list, e.g. blr_domain_name, blr_not_nullable etc.
        assert(false);
        return 0;
    }
}

void firebird::mallocSQLVAR(XSQLDA* pSqlda)
{
    // TODO: confirm the sizings below.
    XSQLVAR* pVar = pSqlda->sqlvar;
    for (int i=0; i < pSqlda->sqld; i++, pVar++)
    {
        int dtype = (pVar->sqltype & ~1); /* drop flag bit for now */
        switch(dtype) {
        case SQL_TEXT:
            pVar->sqldata = (char *)malloc(sizeof(char)*pVar->sqllen);
            break;
        case SQL_VARYING:
            pVar->sqldata = (char *)malloc(sizeof(char)*pVar->sqllen + 2);
            break;
        case SQL_SHORT:
            pVar->sqldata = (char*) malloc(sizeof(sal_Int16));
            break;
        case SQL_LONG:
            pVar->sqldata = (char*) malloc(sizeof(sal_Int32));
            break;
        case SQL_FLOAT:
            pVar->sqldata = (char *)malloc(sizeof(float));
            break;
        case SQL_DOUBLE:
            pVar->sqldata = (char *)malloc(sizeof(double));
            break;
        case SQL_D_FLOAT:
            pVar->sqldata = (char *)malloc(sizeof(double));
            break;
        case SQL_TIMESTAMP:
            pVar->sqldata = (char*) malloc(sizeof(ISC_TIMESTAMP));
            break;
        case SQL_BLOB:
            pVar->sqldata = (char*) malloc(sizeof(ISC_QUAD));
            break;
        case SQL_ARRAY:
            assert(false); // TODO: implement
            break;
        case SQL_TYPE_TIME:
            pVar->sqldata = (char*) malloc(sizeof(ISC_TIME));
            break;
        case SQL_TYPE_DATE:
            pVar->sqldata = (char*) malloc(sizeof(ISC_DATE));
            break;
        case SQL_INT64:
            pVar->sqldata = (char *)malloc(sizeof(sal_Int64));
            break;
        case SQL_NULL:
            assert(false); // TODO: implement
            break;
        case SQL_QUAD:
            assert(false); // TODO: implement
            break;
        default:
            SAL_WARN("connectivity.firebird", "Unknown type: " << dtype);
            assert(false);
            break;
        }
        if (pVar->sqltype & 1)
        {
            /* allocate variable to hold NULL status */
            pVar->sqlind = (short *)malloc(sizeof(short));
        }
    }
}

void firebird::freeSQLVAR(XSQLDA* pSqlda)
{
    XSQLVAR* pVar = pSqlda->sqlvar;
    for (int i=0; i < pSqlda->sqld; i++, pVar++)
    {
        int dtype = (pVar->sqltype & ~1); /* drop flag bit for now */
        switch(dtype) {
        case SQL_TEXT:
        case SQL_VARYING:
        case SQL_SHORT:
        case SQL_LONG:
        case SQL_FLOAT:
        case SQL_DOUBLE:
        case SQL_D_FLOAT:
        case SQL_TIMESTAMP:
        case SQL_BLOB:
        case SQL_INT64:
        case SQL_TYPE_TIME:
        case SQL_TYPE_DATE:
            if(pVar->sqldata)
            {
                free(pVar->sqldata);
                pVar->sqldata = NULL;
            }
            break;
        case SQL_ARRAY:
            assert(false); // TODO: implement
            break;
        case SQL_NULL:
            assert(false); // TODO: implement
            break;
        case SQL_QUAD:
            assert(false); // TODO: implement
            break;
        default:
            SAL_WARN("connectivity.firebird", "Unknown type: " << dtype);
//            assert(false);
            break;
        }

        if (pVar->sqltype & 1)
        {
            if(pVar->sqlind)
            {
                free(pVar->sqlind);
                pVar->sqlind = NULL;
            }
        }
    }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<commit_msg>coverity#1079093 Uncaught exception<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#include "Util.hxx"
#include <rtl/ustrbuf.hxx>

using namespace ::connectivity;

using namespace ::rtl;

using namespace ::com::sun::star;
using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::uno;

OUString firebird::sanitizeIdentifier(const OUString& rIdentifier)
{
    OUString sRet = rIdentifier.trim();
    assert(sRet.getLength() <= 31); // Firebird identifiers cannot be longer than this.

    return sRet;
}

void firebird::evaluateStatusVector(ISC_STATUS_ARRAY& aStatusVector,
                                    const OUString& aCause,
                                    const uno::Reference< XInterface >& _rxContext)
    throw(SQLException)
{
    if (aStatusVector[0]==1 && aStatusVector[1]) // indicates error
    {
        OUStringBuffer buf;
        char msg[512]; // Size is based on suggestion in docs.
        const ISC_STATUS* pStatus = (const ISC_STATUS*) &aStatusVector;

        buf.appendAscii("firebird_sdbc error:");
        try
        {
            while(fb_interpret(msg, sizeof(msg), &pStatus))
            {
                // TODO: verify encoding
                buf.appendAscii("\n*");
                buf.append(OUString(msg, strlen(msg), RTL_TEXTENCODING_UTF8));
            }
        }
        catch (...)
        {
            SAL_WARN("connectivity.firebird", "ignore fb_interpret exception");
        }
        buf.appendAscii("\ncaused by\n'").append(aCause).appendAscii("'\n");

        OUString error = buf.makeStringAndClear();
        SAL_WARN("connectivity.firebird", error);

        throw SQLException( error, _rxContext, OUString(), 1, Any() );
    }
}

sal_Int32 firebird::getColumnTypeFromFBType(short aType)
{
    aType &= ~1; // Remove last bit -- it is used to denote whether column
                 // can store Null, not needed for type determination
    switch (aType)
    {
    case SQL_TEXT:
        return DataType::CHAR;
    case SQL_VARYING:
        return DataType::VARCHAR;
    case SQL_SHORT:
        return DataType::SMALLINT;
    case SQL_LONG:
        return DataType::INTEGER;
    case SQL_FLOAT:
        return DataType::FLOAT;
    case SQL_DOUBLE:
        return DataType::DOUBLE;
    case SQL_D_FLOAT:
        return DataType::DOUBLE;
    case SQL_TIMESTAMP:
        return DataType::TIMESTAMP;
    case SQL_BLOB:
        return DataType::BLOB;
    case SQL_ARRAY:
        return DataType::ARRAY;
    case SQL_TYPE_TIME:
        return DataType::TIME;
    case SQL_TYPE_DATE:
        return DataType::DATE;
    case SQL_INT64:
        return DataType::BIGINT;
    case SQL_NULL:
        return DataType::SQLNULL;
    case SQL_QUAD:      // Is a "Blob ID" according to the docs
        return 0;       // TODO: verify
    default:
        assert(false); // Should never happen
        return 0;
    }
}

OUString firebird::getColumnTypeNameFromFBType(short aType)
{
    aType &= ~1; // Remove last bit -- it is used to denote whether column
                // can store Null, not needed for type determination
    switch (aType)
    {
    case SQL_TEXT:
        return OUString("SQL_TEXT");
    case SQL_VARYING:
        return OUString("SQL_VARYING");
    case SQL_SHORT:
        return OUString("SQL_SHORT");
    case SQL_LONG:
        return OUString("SQL_LONG");
    case SQL_FLOAT:
        return OUString("SQL_FLOAT");
    case SQL_DOUBLE:
        return OUString("SQL_DOUBLE");
    case SQL_D_FLOAT:
        return OUString("SQL_D_FLOAT");
    case SQL_TIMESTAMP:
        return OUString("SQL_TIMESTAMP");
    case SQL_BLOB:
        return OUString("SQL_BLOB");
    case SQL_ARRAY:
        return OUString("SQL_ARRAY");
    case SQL_TYPE_TIME:
        return OUString("SQL_TYPE_TIME");
    case SQL_TYPE_DATE:
        return OUString("SQL_TYPE_DATE");
    case SQL_INT64:
        return OUString("SQL_INT64");
    case SQL_NULL:
        return OUString("SQL_NULL");
    case SQL_QUAD:
        return OUString("SQL_QUAD");
    default:
        assert(false); // Should never happen
        return OUString();
    }
}

short firebird::getFBTypeFromBlrType(short blrType)
{
    switch (blrType)
    {
    case blr_text:
        return SQL_TEXT;
    case blr_text2:
        assert(false);
        return 0; // No idea if this should be supported
    case blr_varying:
        return SQL_VARYING;
    case blr_varying2:
        assert(false);
        return 0; // No idea if this should be supported
    case blr_short:
        return SQL_SHORT;
    case blr_long:
        return SQL_LONG;
    case blr_float:
        return SQL_FLOAT;
    case blr_double:
        return SQL_DOUBLE;
    case blr_d_float:
        return SQL_D_FLOAT;
    case blr_timestamp:
        return SQL_TIMESTAMP;
    case blr_blob:
        return SQL_BLOB;
//     case blr_SQL_ARRAY:
//         return OUString("SQL_ARRAY");
    case blr_sql_time:
        return SQL_TYPE_TIME;
    case blr_sql_date:
        return SQL_TYPE_DATE;
    case blr_int64:
        return SQL_INT64;
//     case SQL_NULL:
//         return OUString("SQL_NULL");
    case blr_quad:
        return SQL_QUAD;
    default:
        // If this happens we have hit one of the extra types in ibase.h
        // look up blr_* for a list, e.g. blr_domain_name, blr_not_nullable etc.
        assert(false);
        return 0;
    }
}

void firebird::mallocSQLVAR(XSQLDA* pSqlda)
{
    // TODO: confirm the sizings below.
    XSQLVAR* pVar = pSqlda->sqlvar;
    for (int i=0; i < pSqlda->sqld; i++, pVar++)
    {
        int dtype = (pVar->sqltype & ~1); /* drop flag bit for now */
        switch(dtype) {
        case SQL_TEXT:
            pVar->sqldata = (char *)malloc(sizeof(char)*pVar->sqllen);
            break;
        case SQL_VARYING:
            pVar->sqldata = (char *)malloc(sizeof(char)*pVar->sqllen + 2);
            break;
        case SQL_SHORT:
            pVar->sqldata = (char*) malloc(sizeof(sal_Int16));
            break;
        case SQL_LONG:
            pVar->sqldata = (char*) malloc(sizeof(sal_Int32));
            break;
        case SQL_FLOAT:
            pVar->sqldata = (char *)malloc(sizeof(float));
            break;
        case SQL_DOUBLE:
            pVar->sqldata = (char *)malloc(sizeof(double));
            break;
        case SQL_D_FLOAT:
            pVar->sqldata = (char *)malloc(sizeof(double));
            break;
        case SQL_TIMESTAMP:
            pVar->sqldata = (char*) malloc(sizeof(ISC_TIMESTAMP));
            break;
        case SQL_BLOB:
            pVar->sqldata = (char*) malloc(sizeof(ISC_QUAD));
            break;
        case SQL_ARRAY:
            assert(false); // TODO: implement
            break;
        case SQL_TYPE_TIME:
            pVar->sqldata = (char*) malloc(sizeof(ISC_TIME));
            break;
        case SQL_TYPE_DATE:
            pVar->sqldata = (char*) malloc(sizeof(ISC_DATE));
            break;
        case SQL_INT64:
            pVar->sqldata = (char *)malloc(sizeof(sal_Int64));
            break;
        case SQL_NULL:
            assert(false); // TODO: implement
            break;
        case SQL_QUAD:
            assert(false); // TODO: implement
            break;
        default:
            SAL_WARN("connectivity.firebird", "Unknown type: " << dtype);
            assert(false);
            break;
        }
        if (pVar->sqltype & 1)
        {
            /* allocate variable to hold NULL status */
            pVar->sqlind = (short *)malloc(sizeof(short));
        }
    }
}

void firebird::freeSQLVAR(XSQLDA* pSqlda)
{
    XSQLVAR* pVar = pSqlda->sqlvar;
    for (int i=0; i < pSqlda->sqld; i++, pVar++)
    {
        int dtype = (pVar->sqltype & ~1); /* drop flag bit for now */
        switch(dtype) {
        case SQL_TEXT:
        case SQL_VARYING:
        case SQL_SHORT:
        case SQL_LONG:
        case SQL_FLOAT:
        case SQL_DOUBLE:
        case SQL_D_FLOAT:
        case SQL_TIMESTAMP:
        case SQL_BLOB:
        case SQL_INT64:
        case SQL_TYPE_TIME:
        case SQL_TYPE_DATE:
            if(pVar->sqldata)
            {
                free(pVar->sqldata);
                pVar->sqldata = NULL;
            }
            break;
        case SQL_ARRAY:
            assert(false); // TODO: implement
            break;
        case SQL_NULL:
            assert(false); // TODO: implement
            break;
        case SQL_QUAD:
            assert(false); // TODO: implement
            break;
        default:
            SAL_WARN("connectivity.firebird", "Unknown type: " << dtype);
//            assert(false);
            break;
        }

        if (pVar->sqltype & 1)
        {
            if(pVar->sqlind)
            {
                free(pVar->sqlind);
                pVar->sqlind = NULL;
            }
        }
    }
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    ArrayCasting.cxx

-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include <vtkDenseArray.h>
#include <vtkSmartPointer.h>
#include <vtkSparseArray.h>
#include <vtkTryDowncast.h>

#include <vtksys/ios/iostream>
#include <vtksys/ios/sstream>
#include <vtksys/stl/stdexcept>

#include <boost/algorithm/string.hpp>

#define VTK_CREATE(type, name) \
  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()

#define test_expression(expression) \
{ \
  if(!(expression)) \
    { \
    vtkstd::ostringstream buffer; \
    buffer << "Expression failed at line " << __LINE__ << ": " << #expression; \
    throw vtkstd::runtime_error(buffer.str()); \
    } \
}

class DowncastTest
{
public:
  DowncastTest(int& count) :
    Count(count)
  {
  }

  template<typename T>
  void operator()(T* vtkNotUsed(array)) const
  {
    ++Count;
  }

  int& Count;

private:
  DowncastTest& operator=(const DowncastTest&);
};

template<template <typename> class TargetT, typename TypesT>
void SuccessTest(vtkObject* source, int line)
{
  int count = 0;
  if(!vtkTryDowncast<TargetT, TypesT>(source, DowncastTest(count)))
    {
    vtkstd::ostringstream buffer;
    buffer << "Expression failed at line " << line;
    throw vtkstd::runtime_error(buffer.str());
    }

  if(count != 1)
    {
    vtkstd::ostringstream buffer;
    buffer << "Functor was called " << count << " times at line " << line;
    throw vtkstd::runtime_error(buffer.str());
    }
}

template<template <typename> class TargetT, typename TypesT>
void FailTest(vtkObject* source, int line)
{
  int count = 0;
  if(vtkTryDowncast<TargetT, TypesT>(source, DowncastTest(count)))
    {
    vtkstd::ostringstream buffer;
    buffer << "Expression failed at line " << line;
    throw vtkstd::runtime_error(buffer.str());
    }

  if(count != 0)
    {
    vtkstd::ostringstream buffer;
    buffer << "Functor was called " << count << " times at line " << line;
    throw vtkstd::runtime_error(buffer.str());
    }
}

/*
// This functor increments array values in-place using a parameter passed via the algorithm (instead of a parameter
// stored in the functor).  It can work with any numeric array type.
struct IncrementValues
{
  template<typename T>
  void operator()(T* array, int amount) const
  {
    for(vtkIdType n = 0; n != array->GetNonNullSize(); ++n)
      array->SetValueN(n, array->GetValueN(n) + amount);
  }
};

// This functor converts strings in-place to a form suitable for case-insensitive comparison.  It's an example of
// how you can write generic code while still specializing functionality on a case-by-case basis, since
// in this situation we want to use some special functionality provided by vtkUnicodeString.
struct FoldCase
{
  template<typename ValueT>
  void operator()(vtkTypedArray<ValueT>* array) const
  {
    for(vtkIdType n = 0; n != array->GetNonNullSize(); ++n)
      {
      ValueT value = array->GetValueN(n);
      boost::algorithm::to_lower(value);
      array->SetValueN(n, value);
      }
  }

  void operator()(vtkTypedArray<vtkUnicodeString>* array) const
  {
    for(vtkIdType n = 0; n != array->GetNonNullSize(); ++n)
      array->SetValueN(n, array->GetValueN(n).fold_case());
  }
};

// This functor efficiently creates a transposed array.  It's one example of how you can create an output array
// with the same type as an input array.
struct Transpose
{
  Transpose(vtkSmartPointer<vtkArray>& result_matrix) : ResultMatrix(result_matrix) {}

  template<typename ValueT>
  void operator()(vtkDenseArray<ValueT>* input) const
  {
    if(input->GetDimensions() != 2 || input->GetExtents()[0] != input->GetExtents()[1])
      throw vtkstd::runtime_error("A square matrix is required.");

    vtkDenseArray<ValueT>* output = vtkDenseArray<ValueT>::SafeDownCast(input->DeepCopy());
    for(vtkIdType i = 0; i != input->GetExtents()[0]; ++i)
      {
      for(vtkIdType j = i + 1; j != input->GetExtents()[1]; ++j)
        {
        output->SetValue(i, j, input->GetValue(j, i));
        output->SetValue(j, i, input->GetValue(i, j));
        }
      }

    this->ResultMatrix = output;
  }

  vtkSmartPointer<vtkArray>& ResultMatrix;
};
*/

//
//
// Here are some examples of how the algorithm might be called.
//
//

int main(int vtkNotUsed(argc), char *vtkNotUsed(argv)[])
{
  try
    {
    VTK_CREATE(vtkDenseArray<int>, dense_int);
    VTK_CREATE(vtkDenseArray<double>, dense_double);
    VTK_CREATE(vtkDenseArray<vtkStdString>, dense_string);
    VTK_CREATE(vtkSparseArray<int>, sparse_int);
    VTK_CREATE(vtkSparseArray<double>, sparse_double);
    VTK_CREATE(vtkSparseArray<vtkStdString>, sparse_string);

    SuccessTest<vtkTypedArray, vtkIntegerTypes>(dense_int, __LINE__);
    FailTest<vtkTypedArray, vtkIntegerTypes>(dense_double, __LINE__);
    FailTest<vtkTypedArray, vtkIntegerTypes>(dense_string, __LINE__);
    SuccessTest<vtkTypedArray, vtkIntegerTypes>(sparse_int, __LINE__);
    FailTest<vtkTypedArray, vtkIntegerTypes>(sparse_double, __LINE__);
    FailTest<vtkTypedArray, vtkIntegerTypes>(sparse_string, __LINE__);

    FailTest<vtkTypedArray, vtkFloatingPointTypes>(dense_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkFloatingPointTypes>(dense_double, __LINE__);
    FailTest<vtkTypedArray, vtkFloatingPointTypes>(dense_string, __LINE__);
    FailTest<vtkTypedArray, vtkFloatingPointTypes>(sparse_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkFloatingPointTypes>(sparse_double, __LINE__);
    FailTest<vtkTypedArray, vtkFloatingPointTypes>(sparse_string, __LINE__);

    SuccessTest<vtkTypedArray, vtkNumericTypes>(dense_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkNumericTypes>(dense_double, __LINE__);
    FailTest<vtkTypedArray, vtkNumericTypes>(dense_string, __LINE__);
    SuccessTest<vtkTypedArray, vtkNumericTypes>(sparse_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkNumericTypes>(sparse_double, __LINE__);
    FailTest<vtkTypedArray, vtkNumericTypes>(sparse_string, __LINE__);

    FailTest<vtkTypedArray, vtkStringTypes>(dense_int, __LINE__);
    FailTest<vtkTypedArray, vtkStringTypes>(dense_double, __LINE__);
    SuccessTest<vtkTypedArray, vtkStringTypes>(dense_string, __LINE__);
    FailTest<vtkTypedArray, vtkStringTypes>(sparse_int, __LINE__);
    FailTest<vtkTypedArray, vtkStringTypes>(sparse_double, __LINE__);
    SuccessTest<vtkTypedArray, vtkStringTypes>(sparse_string, __LINE__);

    SuccessTest<vtkTypedArray, vtkAllTypes>(dense_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkAllTypes>(dense_double, __LINE__);
    SuccessTest<vtkTypedArray, vtkAllTypes>(dense_string, __LINE__);
    SuccessTest<vtkTypedArray, vtkAllTypes>(sparse_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkAllTypes>(sparse_double, __LINE__);
    SuccessTest<vtkTypedArray, vtkAllTypes>(sparse_string, __LINE__);

    SuccessTest<vtkDenseArray, vtkAllTypes>(dense_int, __LINE__);
    FailTest<vtkDenseArray, vtkAllTypes>(sparse_int, __LINE__);
    FailTest<vtkSparseArray, vtkAllTypes>(dense_int, __LINE__);
    SuccessTest<vtkSparseArray, vtkAllTypes>(sparse_int, __LINE__);

    return 0;
    }
  catch(vtkstd::exception& e)
    {
    cerr << e.what() << endl;
    return 1;
    }
}

<commit_msg>COMP: Temporary workaround for clang compilation.<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    ArrayCasting.cxx

-------------------------------------------------------------------------
  Copyright 2008 Sandia Corporation.
  Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
  the U.S. Government retains certain rights in this software.
-------------------------------------------------------------------------

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/

#include <vtkDenseArray.h>
#include <vtkSmartPointer.h>
#include <vtkSparseArray.h>
#include <vtkTryDowncast.h>

#include <vtksys/ios/iostream>
#include <vtksys/ios/sstream>
#include <vtksys/stl/stdexcept>

#include <boost/algorithm/string.hpp>

#define VTK_CREATE(type, name) \
  vtkSmartPointer<type> name = vtkSmartPointer<type>::New()

#define test_expression(expression) \
{ \
  if(!(expression)) \
    { \
    vtkstd::ostringstream buffer; \
    buffer << "Expression failed at line " << __LINE__ << ": " << #expression; \
    throw vtkstd::runtime_error(buffer.str()); \
    } \
}

class DowncastTest
{
public:
  DowncastTest(int& count) :
    Count(count)
  {
  }

  template<typename T>
  void operator()(T* vtkNotUsed(array)) const
  {
    ++Count;
  }

  int& Count;

private:
  DowncastTest& operator=(const DowncastTest&);
};

template<template <typename> class TargetT, typename TypesT>
void SuccessTest(vtkObject* source, int line)
{
  int count = 0;
  if(!vtkTryDowncast<TargetT, TypesT>(source, DowncastTest(count)))
    {
    vtkstd::ostringstream buffer;
    buffer << "Expression failed at line " << line;
    throw vtkstd::runtime_error(buffer.str());
    }

  if(count != 1)
    {
    vtkstd::ostringstream buffer;
    buffer << "Functor was called " << count << " times at line " << line;
    throw vtkstd::runtime_error(buffer.str());
    }
}

template<template <typename> class TargetT, typename TypesT>
void FailTest(vtkObject* source, int line)
{
  int count = 0;
  if(vtkTryDowncast<TargetT, TypesT>(source, DowncastTest(count)))
    {
    vtkstd::ostringstream buffer;
    buffer << "Expression failed at line " << line;
    throw vtkstd::runtime_error(buffer.str());
    }

  if(count != 0)
    {
    vtkstd::ostringstream buffer;
    buffer << "Functor was called " << count << " times at line " << line;
    throw vtkstd::runtime_error(buffer.str());
    }
}

/*
// This functor increments array values in-place using a parameter passed via the algorithm (instead of a parameter
// stored in the functor).  It can work with any numeric array type.
struct IncrementValues
{
  template<typename T>
  void operator()(T* array, int amount) const
  {
    for(vtkIdType n = 0; n != array->GetNonNullSize(); ++n)
      array->SetValueN(n, array->GetValueN(n) + amount);
  }
};

// This functor converts strings in-place to a form suitable for case-insensitive comparison.  It's an example of
// how you can write generic code while still specializing functionality on a case-by-case basis, since
// in this situation we want to use some special functionality provided by vtkUnicodeString.
struct FoldCase
{
  template<typename ValueT>
  void operator()(vtkTypedArray<ValueT>* array) const
  {
    for(vtkIdType n = 0; n != array->GetNonNullSize(); ++n)
      {
      ValueT value = array->GetValueN(n);
      boost::algorithm::to_lower(value);
      array->SetValueN(n, value);
      }
  }

  void operator()(vtkTypedArray<vtkUnicodeString>* array) const
  {
    for(vtkIdType n = 0; n != array->GetNonNullSize(); ++n)
      array->SetValueN(n, array->GetValueN(n).fold_case());
  }
};

// This functor efficiently creates a transposed array.  It's one example of how you can create an output array
// with the same type as an input array.
struct Transpose
{
  Transpose(vtkSmartPointer<vtkArray>& result_matrix) : ResultMatrix(result_matrix) {}

  template<typename ValueT>
  void operator()(vtkDenseArray<ValueT>* input) const
  {
    if(input->GetDimensions() != 2 || input->GetExtents()[0] != input->GetExtents()[1])
      throw vtkstd::runtime_error("A square matrix is required.");

    vtkDenseArray<ValueT>* output = vtkDenseArray<ValueT>::SafeDownCast(input->DeepCopy());
    for(vtkIdType i = 0; i != input->GetExtents()[0]; ++i)
      {
      for(vtkIdType j = i + 1; j != input->GetExtents()[1]; ++j)
        {
        output->SetValue(i, j, input->GetValue(j, i));
        output->SetValue(j, i, input->GetValue(i, j));
        }
      }

    this->ResultMatrix = output;
  }

  vtkSmartPointer<vtkArray>& ResultMatrix;
};
*/

//
//
// Here are some examples of how the algorithm might be called.
//
//

int main(int vtkNotUsed(argc), char *vtkNotUsed(argv)[])
{
  try
    {
    /* this "if" is a temporary workaround for the clang compiler,
     * everything inside "#ifdef __clang__" should be removed when
     * clang no longer needs these templates to be instantiated. */
#ifdef __clang__
    VTK_CREATE(vtkDenseArray<vtkUnicodeString>, dense_unicode);
    VTK_CREATE(vtkDenseArray<vtkStdString>, dense_string);
    VTK_CREATE(vtkDenseArray<vtkTypeFloat32>, dense_float);
    VTK_CREATE(vtkDenseArray<vtkTypeFloat64>, dense_double);
    VTK_CREATE(vtkDenseArray<vtkTypeUInt8>, dense_uchar);
    VTK_CREATE(vtkDenseArray<vtkTypeInt8>, dense_schar);
    VTK_CREATE(vtkDenseArray<vtkTypeUInt16>, dense_ushort);
    VTK_CREATE(vtkDenseArray<vtkTypeInt16>, dense_short);
    VTK_CREATE(vtkDenseArray<vtkTypeUInt32>, dense_uint);
    VTK_CREATE(vtkDenseArray<vtkTypeInt32>, dense_int);
    VTK_CREATE(vtkDenseArray<vtkTypeUInt64>, dense_ulonglong);
    VTK_CREATE(vtkDenseArray<vtkTypeInt64>, dense_longlong);
    VTK_CREATE(vtkDenseArray<vtkIdType>, dense_idtype);
    VTK_CREATE(vtkSparseArray<vtkUnicodeString>, sparse_unicode);
    VTK_CREATE(vtkSparseArray<vtkStdString>, sparse_string);
    VTK_CREATE(vtkSparseArray<vtkTypeFloat32>, sparse_float);
    VTK_CREATE(vtkSparseArray<vtkTypeFloat64>, sparse_double);
    VTK_CREATE(vtkSparseArray<vtkTypeUInt8>, sparse_uchar);
    VTK_CREATE(vtkSparseArray<vtkTypeInt8>, sparse_schar);
    VTK_CREATE(vtkSparseArray<vtkTypeUInt16>, sparse_ushort);
    VTK_CREATE(vtkSparseArray<vtkTypeInt16>, sparse_short);
    VTK_CREATE(vtkSparseArray<vtkTypeUInt32>, sparse_uint);
    VTK_CREATE(vtkSparseArray<vtkTypeInt32>, sparse_int);
    VTK_CREATE(vtkSparseArray<vtkTypeUInt64>, sparse_ulonglong);
    VTK_CREATE(vtkSparseArray<vtkTypeInt64>, sparse_longlong);
    VTK_CREATE(vtkSparseArray<vtkIdType>, sparse_idtype);
#else
    VTK_CREATE(vtkDenseArray<int>, dense_int);
    VTK_CREATE(vtkDenseArray<double>, dense_double);
    VTK_CREATE(vtkDenseArray<vtkStdString>, dense_string);
    VTK_CREATE(vtkSparseArray<int>, sparse_int);
    VTK_CREATE(vtkSparseArray<double>, sparse_double);
    VTK_CREATE(vtkSparseArray<vtkStdString>, sparse_string);
#endif

    SuccessTest<vtkTypedArray, vtkIntegerTypes>(dense_int, __LINE__);
    FailTest<vtkTypedArray, vtkIntegerTypes>(dense_double, __LINE__);
    FailTest<vtkTypedArray, vtkIntegerTypes>(dense_string, __LINE__);
    SuccessTest<vtkTypedArray, vtkIntegerTypes>(sparse_int, __LINE__);
    FailTest<vtkTypedArray, vtkIntegerTypes>(sparse_double, __LINE__);
    FailTest<vtkTypedArray, vtkIntegerTypes>(sparse_string, __LINE__);

    FailTest<vtkTypedArray, vtkFloatingPointTypes>(dense_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkFloatingPointTypes>(dense_double, __LINE__);
    FailTest<vtkTypedArray, vtkFloatingPointTypes>(dense_string, __LINE__);
    FailTest<vtkTypedArray, vtkFloatingPointTypes>(sparse_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkFloatingPointTypes>(sparse_double, __LINE__);
    FailTest<vtkTypedArray, vtkFloatingPointTypes>(sparse_string, __LINE__);

    SuccessTest<vtkTypedArray, vtkNumericTypes>(dense_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkNumericTypes>(dense_double, __LINE__);
    FailTest<vtkTypedArray, vtkNumericTypes>(dense_string, __LINE__);
    SuccessTest<vtkTypedArray, vtkNumericTypes>(sparse_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkNumericTypes>(sparse_double, __LINE__);
    FailTest<vtkTypedArray, vtkNumericTypes>(sparse_string, __LINE__);

    FailTest<vtkTypedArray, vtkStringTypes>(dense_int, __LINE__);
    FailTest<vtkTypedArray, vtkStringTypes>(dense_double, __LINE__);
    SuccessTest<vtkTypedArray, vtkStringTypes>(dense_string, __LINE__);
    FailTest<vtkTypedArray, vtkStringTypes>(sparse_int, __LINE__);
    FailTest<vtkTypedArray, vtkStringTypes>(sparse_double, __LINE__);
    SuccessTest<vtkTypedArray, vtkStringTypes>(sparse_string, __LINE__);

    SuccessTest<vtkTypedArray, vtkAllTypes>(dense_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkAllTypes>(dense_double, __LINE__);
    SuccessTest<vtkTypedArray, vtkAllTypes>(dense_string, __LINE__);
    SuccessTest<vtkTypedArray, vtkAllTypes>(sparse_int, __LINE__);
    SuccessTest<vtkTypedArray, vtkAllTypes>(sparse_double, __LINE__);
    SuccessTest<vtkTypedArray, vtkAllTypes>(sparse_string, __LINE__);

    SuccessTest<vtkDenseArray, vtkAllTypes>(dense_int, __LINE__);
    FailTest<vtkDenseArray, vtkAllTypes>(sparse_int, __LINE__);
    FailTest<vtkSparseArray, vtkAllTypes>(dense_int, __LINE__);
    SuccessTest<vtkSparseArray, vtkAllTypes>(sparse_int, __LINE__);

    return 0;
    }
  catch(vtkstd::exception& e)
    {
    cerr << e.what() << endl;
    return 1;
    }
}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTableExtentTranslator.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkTableExtentTranslator.h"
#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkTableExtentTranslator, "1.7");
vtkStandardNewMacro(vtkTableExtentTranslator);

//----------------------------------------------------------------------------
vtkTableExtentTranslator::vtkTableExtentTranslator()
{
  this->ExtentTable = 0;
  this->MaximumGhostLevel = 0;
  this->PieceAvailable = 0;
}

//----------------------------------------------------------------------------
vtkTableExtentTranslator::~vtkTableExtentTranslator()
{
  this->SetNumberOfPieces(0);
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  if(this->ExtentTable)
    {
    vtkIndent nextIndent = indent.GetNextIndent();
    int* extent = this->ExtentTable;
    int i;

    os << indent << "ExtentTable: 0: "
       << extent[0] << " " << extent[1] << " "
       << extent[2] << " " << extent[3] << " "
       << extent[4] << " " << extent[5] << "\n";
    for(i=1;i < this->NumberOfPieces;++i)
      {
      extent += 6;
      os << nextIndent << "             " << i << ": "
         << extent[0] << " " << extent[1] << " "
         << extent[2] << " " << extent[3] << " "
         << extent[4] << " " << extent[5] << "\n";
      }
    }
  else
    {
    os << indent << "ExtentTable: (none)\n";
    }
  os << indent << "MaximumGhostLevel: " << this->MaximumGhostLevel << "\n";
  os << indent << "NumberOfPiecesInTable: "
     << this->NumberOfPiecesInTable << "\n";
  if(this->PieceAvailable)
    {
    vtkIndent nextIndent = indent.GetNextIndent();
    int* available = this->PieceAvailable;
    int i;

    os << indent << "PieceAvailable: 0: " << *available << "\n";
    for(i=1;i < this->NumberOfPieces;++i)
      {
      ++available;
      os << nextIndent << "                " << i << ": "
         << *available << "\n";
      }
    }
  else
    {
    os << indent << "PieceAvailable: (none)\n";
    }
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::SetNumberOfPieces(int pieces)
{
  // Allocate a table for this number of pieces.
  if(this->NumberOfPiecesInTable == 0)
    {
    this->SetNumberOfPiecesInTable(pieces);
    }
  this->Superclass::SetNumberOfPieces(pieces);
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::SetNumberOfPiecesInTable(int pieces)
{
  // Make sure we are really changing the number of pieces.
  if(this->NumberOfPiecesInTable == pieces)
    {
    return;
    }

  // The default number of pieces returned is the real number of
  // pieces.
  this->Superclass::SetNumberOfPieces(pieces);

  // Clean out any old extent table.
  if(this->ExtentTable)
    {
    delete [] this->ExtentTable;
    this->ExtentTable = 0;
    }
  if(this->PieceAvailable)
    {
    delete [] this->PieceAvailable;
    this->PieceAvailable = 0;
    }

  // Create and initialize a new extent table if there are any pieces.
  // Assume all pieces are available.
  if(this->NumberOfPiecesInTable > 0)
    {
    this->ExtentTable = new int[this->NumberOfPiecesInTable*6];
    this->PieceAvailable = new int[this->NumberOfPiecesInTable];
    int i;
    for(i=0;i < this->NumberOfPiecesInTable;++i)
      {
      int* extent = this->ExtentTable + i*6;
      extent[0] = extent[2] = extent[4] = 0;
      extent[1] = extent[3] = extent[5] = -1;
      this->PieceAvailable[i] = 1;
      }
    }
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::SetExtentForPiece(int piece, int* extent)
{
  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= this->NumberOfPiecesInTable))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    return;
    }
  memcpy(this->ExtentTable+piece*6, extent, sizeof(int)*6);
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::GetExtentForPiece(int piece, int* extent)
{
  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= this->NumberOfPiecesInTable))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    extent[0] = extent[2] = extent[4] = 0;
    extent[1] = extent[3] = extent[5] = -1;
    return;
    }
  memcpy(extent, this->ExtentTable+piece*6, sizeof(int)*6);
}

//----------------------------------------------------------------------------
int* vtkTableExtentTranslator::GetExtentForPiece(int piece)
{
  static int emptyExtent[6] = {0,-1,0,-1,0,-1};
  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= this->NumberOfPiecesInTable))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    return emptyExtent;
    }
  return this->ExtentTable+piece*6;
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::SetPieceAvailable(int piece, int available)
{
  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= this->NumberOfPiecesInTable))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    }
  this->PieceAvailable[piece] = available?1:0;
}

//----------------------------------------------------------------------------
int vtkTableExtentTranslator::GetPieceAvailable(int piece)
{
  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= this->NumberOfPiecesInTable))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    return 0;
    }
  return this->PieceAvailable[piece];
}

//----------------------------------------------------------------------------
int vtkTableExtentTranslator::PieceToExtentByPoints()
{
  vtkErrorMacro("PieceToExtentByPoints not supported.");
  return 0;
}

//----------------------------------------------------------------------------
int
vtkTableExtentTranslator::PieceToExtentThreadSafe(int piece, int numPieces,
                                                  int ghostLevel,
                                                  int *wholeExtent,
                                                  int *resultExtent,
                                                  int vtkNotUsed(splitMode),
                                                  int byPoints)
{
  if (byPoints)
    {
    vtkErrorMacro("PieceToExtentByPoints not supported.");
    return 0;
    }

  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= numPieces))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    return 0;
    }

  if(ghostLevel > this->MaximumGhostLevel)
    {
    vtkWarningMacro("Ghost level " << ghostLevel
                    << " is larger than MaximumGhostLevel "
                    << this->MaximumGhostLevel << ".  Using the maximum.");
    ghostLevel = this->MaximumGhostLevel;
    }

  if(numPieces == 1)
    {
    // The number of pieces requested is one.  Return the whole extent.
    memcpy(resultExtent, wholeExtent, sizeof(int)*6);
    }
  else if(piece < this->NumberOfPiecesInTable)
    {
    // The requested piece is beyond the table.  Return an empty extent.
    resultExtent[0] = 0;
    resultExtent[1] = -1;
    resultExtent[2] = 0;
    resultExtent[3] = -1;
    resultExtent[4] = 0;
    resultExtent[5] = -1;
    }
  else
    {
    // Return the extent from the table entry.
    memcpy(resultExtent, this->ExtentTable+piece*6, sizeof(int)*6);
    }

  if(((resultExtent[1] - resultExtent[0] + 1)*
      (resultExtent[3] - resultExtent[2] + 1)*
      (resultExtent[5] - resultExtent[4] + 1)) == 0)
    {
    return 0;
    }

  if(ghostLevel > 0)
    {
    resultExtent[0] -= this->GhostLevel;
    resultExtent[1] += this->GhostLevel;
    resultExtent[2] -= this->GhostLevel;
    resultExtent[3] += this->GhostLevel;
    resultExtent[4] -= this->GhostLevel;
    resultExtent[5] += this->GhostLevel;

    if (resultExtent[0] < wholeExtent[0])
      {
      resultExtent[0] = wholeExtent[0];
      }
    if (resultExtent[1] > wholeExtent[1])
      {
      resultExtent[1] = wholeExtent[1];
      }
    if (resultExtent[2] < wholeExtent[2])
      {
      resultExtent[2] = wholeExtent[2];
      }
    if (resultExtent[3] > wholeExtent[3])
      {
      resultExtent[3] = wholeExtent[3];
      }
    if (resultExtent[4] < wholeExtent[4])
      {
      resultExtent[4] = wholeExtent[4];
      }
    if (resultExtent[5] > wholeExtent[5])
      {
      resultExtent[5] = wholeExtent[5];
      }
    }

  return 1;

}

//----------------------------------------------------------------------------
int vtkTableExtentTranslator::PieceToExtent()
{
  return this->PieceToExtentThreadSafe(this->Piece, this->NumberOfPieces,
                                       this->GhostLevel,
                                       this->WholeExtent,
                                       this->Extent,
                                       this->SplitMode,
                                       0);
}
<commit_msg>fix segfault<commit_after>/*=========================================================================

  Program:   Visualization Toolkit
  Module:    vtkTableExtentTranslator.cxx

  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
  All rights reserved.
  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notice for more information.

=========================================================================*/
#include "vtkTableExtentTranslator.h"
#include "vtkObjectFactory.h"

vtkCxxRevisionMacro(vtkTableExtentTranslator, "1.8");
vtkStandardNewMacro(vtkTableExtentTranslator);

//----------------------------------------------------------------------------
vtkTableExtentTranslator::vtkTableExtentTranslator()
{
  this->ExtentTable = 0;
  this->MaximumGhostLevel = 0;
  this->PieceAvailable = 0;
}

//----------------------------------------------------------------------------
vtkTableExtentTranslator::~vtkTableExtentTranslator()
{
  this->SetNumberOfPieces(0);
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::PrintSelf(ostream& os, vtkIndent indent)
{
  this->Superclass::PrintSelf(os, indent);
  if(this->ExtentTable)
    {
    vtkIndent nextIndent = indent.GetNextIndent();
    int* extent = this->ExtentTable;
    int i;

    os << indent << "ExtentTable: 0: "
       << extent[0] << " " << extent[1] << " "
       << extent[2] << " " << extent[3] << " "
       << extent[4] << " " << extent[5] << "\n";
    for(i=1;i < this->NumberOfPieces;++i)
      {
      extent += 6;
      os << nextIndent << "             " << i << ": "
         << extent[0] << " " << extent[1] << " "
         << extent[2] << " " << extent[3] << " "
         << extent[4] << " " << extent[5] << "\n";
      }
    }
  else
    {
    os << indent << "ExtentTable: (none)\n";
    }
  os << indent << "MaximumGhostLevel: " << this->MaximumGhostLevel << "\n";
  os << indent << "NumberOfPiecesInTable: "
     << this->NumberOfPiecesInTable << "\n";
  if(this->PieceAvailable)
    {
    vtkIndent nextIndent = indent.GetNextIndent();
    int* available = this->PieceAvailable;
    int i;

    os << indent << "PieceAvailable: 0: " << *available << "\n";
    for(i=1;i < this->NumberOfPieces;++i)
      {
      ++available;
      os << nextIndent << "                " << i << ": "
         << *available << "\n";
      }
    }
  else
    {
    os << indent << "PieceAvailable: (none)\n";
    }
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::SetNumberOfPieces(int pieces)
{
  // Allocate a table for this number of pieces.
  if(this->NumberOfPiecesInTable == 0)
    {
    this->SetNumberOfPiecesInTable(pieces);
    }
  this->Superclass::SetNumberOfPieces(pieces);
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::SetNumberOfPiecesInTable(int pieces)
{
  // Make sure we are really changing the number of pieces.
  if(this->NumberOfPiecesInTable == pieces)
    {
    return;
    }

  // The default number of pieces returned is the real number of
  // pieces.
  this->Superclass::SetNumberOfPieces(pieces);

  // Clean out any old extent table.
  if(this->ExtentTable)
    {
    delete [] this->ExtentTable;
    this->ExtentTable = 0;
    }
  if(this->PieceAvailable)
    {
    delete [] this->PieceAvailable;
    this->PieceAvailable = 0;
    }

  // Create and initialize a new extent table if there are any pieces.
  // Assume all pieces are available.
  if(this->NumberOfPiecesInTable > 0)
    {
    this->ExtentTable = new int[this->NumberOfPiecesInTable*6];
    this->PieceAvailable = new int[this->NumberOfPiecesInTable];
    int i;
    for(i=0;i < this->NumberOfPiecesInTable;++i)
      {
      int* extent = this->ExtentTable + i*6;
      extent[0] = extent[2] = extent[4] = 0;
      extent[1] = extent[3] = extent[5] = -1;
      this->PieceAvailable[i] = 1;
      }
    }
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::SetExtentForPiece(int piece, int* extent)
{
  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= this->NumberOfPiecesInTable))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    return;
    }
  memcpy(this->ExtentTable+piece*6, extent, sizeof(int)*6);
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::GetExtentForPiece(int piece, int* extent)
{
  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= this->NumberOfPiecesInTable))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    extent[0] = extent[2] = extent[4] = 0;
    extent[1] = extent[3] = extent[5] = -1;
    return;
    }
  memcpy(extent, this->ExtentTable+piece*6, sizeof(int)*6);
}

//----------------------------------------------------------------------------
int* vtkTableExtentTranslator::GetExtentForPiece(int piece)
{
  static int emptyExtent[6] = {0,-1,0,-1,0,-1};
  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= this->NumberOfPiecesInTable))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    return emptyExtent;
    }
  return this->ExtentTable+piece*6;
}

//----------------------------------------------------------------------------
void vtkTableExtentTranslator::SetPieceAvailable(int piece, int available)
{
  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= this->NumberOfPiecesInTable))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    return;
    }
  this->PieceAvailable[piece] = available?1:0;
}

//----------------------------------------------------------------------------
int vtkTableExtentTranslator::GetPieceAvailable(int piece)
{
  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= this->NumberOfPiecesInTable))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    return 0;
    }
  return this->PieceAvailable[piece];
}

//----------------------------------------------------------------------------
int vtkTableExtentTranslator::PieceToExtentByPoints()
{
  vtkErrorMacro("PieceToExtentByPoints not supported.");
  return 0;
}

//----------------------------------------------------------------------------
int
vtkTableExtentTranslator::PieceToExtentThreadSafe(int piece, int numPieces,
                                                  int ghostLevel,
                                                  int *wholeExtent,
                                                  int *resultExtent,
                                                  int vtkNotUsed(splitMode),
                                                  int byPoints)
{
  if (byPoints)
    {
    vtkErrorMacro("PieceToExtentByPoints not supported.");
    return 0;
    }

  if((!this->ExtentTable) || (piece < 0) ||
     (piece >= numPieces))
    {
    vtkErrorMacro("Piece " << piece << " does not exist.");
    return 0;
    }

  if(ghostLevel > this->MaximumGhostLevel)
    {
    vtkWarningMacro("Ghost level " << ghostLevel
                    << " is larger than MaximumGhostLevel "
                    << this->MaximumGhostLevel << ".  Using the maximum.");
    ghostLevel = this->MaximumGhostLevel;
    }

  if(numPieces == 1)
    {
    // The number of pieces requested is one.  Return the whole extent.
    memcpy(resultExtent, wholeExtent, sizeof(int)*6);
    }
  else if(piece < this->NumberOfPiecesInTable)
    {
    // The requested piece is beyond the table.  Return an empty extent.
    resultExtent[0] = 0;
    resultExtent[1] = -1;
    resultExtent[2] = 0;
    resultExtent[3] = -1;
    resultExtent[4] = 0;
    resultExtent[5] = -1;
    }
  else
    {
    // Return the extent from the table entry.
    memcpy(resultExtent, this->ExtentTable+piece*6, sizeof(int)*6);
    }

  if(((resultExtent[1] - resultExtent[0] + 1)*
      (resultExtent[3] - resultExtent[2] + 1)*
      (resultExtent[5] - resultExtent[4] + 1)) == 0)
    {
    return 0;
    }

  if(ghostLevel > 0)
    {
    resultExtent[0] -= this->GhostLevel;
    resultExtent[1] += this->GhostLevel;
    resultExtent[2] -= this->GhostLevel;
    resultExtent[3] += this->GhostLevel;
    resultExtent[4] -= this->GhostLevel;
    resultExtent[5] += this->GhostLevel;

    if (resultExtent[0] < wholeExtent[0])
      {
      resultExtent[0] = wholeExtent[0];
      }
    if (resultExtent[1] > wholeExtent[1])
      {
      resultExtent[1] = wholeExtent[1];
      }
    if (resultExtent[2] < wholeExtent[2])
      {
      resultExtent[2] = wholeExtent[2];
      }
    if (resultExtent[3] > wholeExtent[3])
      {
      resultExtent[3] = wholeExtent[3];
      }
    if (resultExtent[4] < wholeExtent[4])
      {
      resultExtent[4] = wholeExtent[4];
      }
    if (resultExtent[5] > wholeExtent[5])
      {
      resultExtent[5] = wholeExtent[5];
      }
    }

  return 1;

}

//----------------------------------------------------------------------------
int vtkTableExtentTranslator::PieceToExtent()
{
  return this->PieceToExtentThreadSafe(this->Piece, this->NumberOfPieces,
                                       this->GhostLevel,
                                       this->WholeExtent,
                                       this->Extent,
                                       this->SplitMode,
                                       0);
}
<|endoftext|>


<commit_before>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkSurface.h"
#include "mitkBaseProcess.h"
#include "vtkPolyData.h"
#include "mitkXMLWriter.h"
#include "mitkXMLReader.h"
#include <vtkPolyDataWriter.h>
//#include <vtkPolyDataReader.h>
#include <vtkSTLWriter.h>
#include "mitkSurfaceVtkWriter.h"
#include "mitkDataTreeNodeFactory.h"
#include <itkSmartPointerForwardReference.txx>

void mitk::Surface::SetVtkPolyData( vtkPolyData* polydata, unsigned int t )
{
  if ( polydata == NULL )
    return ;

  if ( t >= m_PolyDataSeries.size() )
  {
    m_PolyDataSeries.resize( t + 1, NULL );
    Initialize(t+1);
  }
  m_PolyDataSeries[ t ] = polydata;
  //@todo why do we have to call m_VtkPolyData->Register(NULL?)
  m_PolyDataSeries[ t ]->Register( NULL );
  this->Modified();
  m_CalculateBoundingBox = true;
}

void mitk::Surface::Initialize(unsigned int timeSteps)
{
  mitk::TimeSlicedGeometry::Pointer timeGeometry = this->GetTimeSlicedGeometry();

  mitk::Geometry3D::Pointer g3d = mitk::Geometry3D::New();
  g3d->Initialize();
  mitk::ScalarType timeBounds[] = {0.0, 1.0};
  g3d->SetTimeBounds( timeBounds );
  //
  // The geometry is propagated automatically to the other items,
  // if EvenlyTimed is true...
  //
  timeGeometry->InitializeEvenlyTimed( g3d.GetPointer(), timeSteps );

  vtkPolyData* pdnull = NULL;
  m_PolyDataSeries.reserve(timeSteps);
  m_PolyDataSeries.assign(timeSteps, pdnull);
}

vtkPolyData* mitk::Surface::GetVtkPolyData( unsigned int t )
{

  if ( t < m_PolyDataSeries.size() )
  {
    vtkPolyData* polydata = m_PolyDataSeries[ t ];
    if((polydata==NULL) && (GetSource().GetPointer()!=NULL))
    {
      RegionType requestedregion;
      requestedregion.SetIndex(3, t);
      requestedregion.SetSize(3, 1);
      SetRequestedRegion(&requestedregion);
      GetSource()->Update();
    }
    polydata = m_PolyDataSeries[ t ];
    return polydata;
  }
  else
    return NULL;
}

//##ModelId=3E70F66100C4
mitk::Surface::Surface() : m_CalculateBoundingBox( false )
{

}

//##ModelId=3E70F66100CA
mitk::Surface::~Surface()
{
  for ( VTKPolyDataSeries::iterator it = m_PolyDataSeries.begin(); it != m_PolyDataSeries.end(); ++it )
  {
    if ( ( *it ) != NULL )
      ( *it )->Delete();
  }
}

//##ModelId=3E70F66100AE
void mitk::Surface::UpdateOutputInformation()
{
  if ( this->GetSource() )
  {
    this->GetSource()->UpdateOutputInformation();
  }
  if ( ( m_CalculateBoundingBox ) && ( m_PolyDataSeries.size() > 0 ) )
    CalculateBoundingBox();
  else
    GetTimeSlicedGeometry()->UpdateInformation();
}

void mitk::Surface::CalculateBoundingBox()
{
  //
  // first make sure, that the associated time sliced geometry has
  // the same number of geometry 3d's as vtkPolyDatas are present
  //
  mitk::TimeSlicedGeometry* timeGeometry = GetTimeSlicedGeometry();
  if ( timeGeometry->GetTimeSteps() != m_PolyDataSeries.size() )
  {
    itkExceptionMacro(<<"timeGeometry->GetTimeSteps() != m_PolyDataSeries.size() -- use Initialize(timeSteps) with correct number of timeSteps!");
  }

  //
  // Iterate over the vtkPolyDatas and update the Geometry
  // information of each of the items.
  //
  for ( unsigned int i = 0 ; i < m_PolyDataSeries.size() ; ++i )
  {
    vtkPolyData* polyData = m_PolyDataSeries[ i ];
    vtkFloatingPointType bounds[ ] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
    if ( ( polyData != NULL ) && ( polyData->GetNumberOfPoints() > 0 ) )
    {
      polyData->Update();
      polyData->ComputeBounds();
      polyData->GetBounds( bounds );
    }
    mitk::Geometry3D::Pointer g3d = timeGeometry->GetGeometry3D( i );
    assert( g3d.IsNotNull() );
    g3d->SetFloatBounds( bounds );
  }
  timeGeometry->UpdateInformation();

  mitk::BoundingBox::Pointer bb = const_cast<mitk::BoundingBox*>( timeGeometry->GetBoundingBox() );
  itkDebugMacro( << "boundingbox min: "<< bb->GetMinimum());
  itkDebugMacro( << "boundingbox max: "<< bb->GetMaximum());
  m_CalculateBoundingBox = false;
}

//##ModelId=3E70F66100B0
void mitk::Surface::SetRequestedRegionToLargestPossibleRegion()
{
  m_RequestedRegion = GetLargestPossibleRegion();
}

//##ModelId=3E70F66100B6

bool mitk::Surface::RequestedRegionIsOutsideOfTheBufferedRegion()
{
  RegionType::IndexValueType end = m_RequestedRegion.GetIndex(3)+m_RequestedRegion.GetSize(3);

  if(((RegionType::IndexValueType)m_PolyDataSeries.size())<end)
    return true;

  for( RegionType::IndexValueType t=m_RequestedRegion.GetIndex(3); t<end; ++t )
    if(m_PolyDataSeries[t]==NULL)
      return true;

  return false;
}

//##ModelId=3E70F66100B8
bool mitk::Surface::VerifyRequestedRegion()
{
  if( (m_RequestedRegion.GetIndex(3)>=0) &&
      (m_RequestedRegion.GetIndex(3)+m_RequestedRegion.GetSize(3)<=m_PolyDataSeries.size()) )
    return true;

  return false;
}

//##ModelId=3E70F66100BA
void mitk::Surface::SetRequestedRegion( itk::DataObject *data )
{
  mitk::Surface *surfaceData;

  surfaceData = dynamic_cast<mitk::Surface*>(data);

  if (surfaceData)
  {
    m_RequestedRegion = surfaceData->GetRequestedRegion();
  }
  else
  {
    // pointer could not be cast back down
    itkExceptionMacro( << "mitk::Surface::SetRequestedRegion(DataObject*) cannot cast " << typeid(data).name() << " to " << typeid(Surface*).name() );
  }
}

void mitk::Surface::SetRequestedRegion(Surface::RegionType *region)  //by arin
{
  if(region!=NULL)
  {
    m_RequestedRegion = *region;
  }
  else
  {
    // pointer could not be cast back down
    itkExceptionMacro( << "mitk::Surface::SetRequestedRegion(Surface::RegionType*) cannot cast " << typeid(region).name() << " to " << typeid(Surface*).name() );
  }
}

//##ModelId=3E70F66100C1

void mitk::Surface::CopyInformation( const itk::DataObject * )
{}

void mitk::Surface::Update()
{
  if ( GetSource() == NULL )
  {
    for ( VTKPolyDataSeries::iterator it = m_PolyDataSeries.begin() ; it != m_PolyDataSeries.end() ; ++it )
    {
      if ( ( *it ) != NULL )
        ( *it )->Update();
    }
  }
  Superclass::Update();
}

void mitk::Surface::Resize( unsigned int timeSteps )
{
  m_PolyDataSeries.resize( timeSteps, NULL );
  this->Modified();
  m_CalculateBoundingBox = true;
}

bool mitk::Surface::WriteXMLData( XMLWriter& xmlWriter )
{
  BaseData::WriteXMLData( xmlWriter );
  std::string fileName = xmlWriter.GetRelativePath();

  if(xmlWriter.IsFileExtension(".vtk", fileName))
  {
    xmlWriter.WriteProperty( XMLReader::FILENAME, fileName.c_str() );

    if(xmlWriter.SaveSourceFiles()){
      mitk::SurfaceVtkWriter<vtkPolyDataWriter>::Pointer writer = mitk::SurfaceVtkWriter<vtkPolyDataWriter>::New();
      writer->SetInput( this );
      fileName = xmlWriter.GetAbsolutePath();
      if(!xmlWriter.IsFileExtension(".vtk", fileName))
        fileName += ".vtk";
      writer->SetFileName( fileName.c_str() );
      writer->Write();
    }
  }
  else
  {
    if(!xmlWriter.IsFileExtension(".stl", fileName))
      fileName += ".stl";
    xmlWriter.WriteProperty( XMLReader::FILENAME, fileName.c_str() );

    if(xmlWriter.SaveSourceFiles()){
      mitk::SurfaceVtkWriter<vtkSTLWriter>::Pointer writer = mitk::SurfaceVtkWriter<vtkSTLWriter>::New();
      writer->SetInput( this );
      fileName = xmlWriter.GetAbsolutePath();
      if(!xmlWriter.IsFileExtension(".stl", fileName))
        fileName += ".stl";
      writer->SetFileName( fileName.c_str() );
      writer->Write();
    }
  }
  return true;
}

bool mitk::Surface::ReadXMLData( XMLReader& xmlReader )
{
  BaseData::ReadXMLData( xmlReader );
  std::string fileName;
  xmlReader.GetAttribute( XMLReader::FILENAME, fileName );

  std::cout << fileName << std::endl;

  mitk::DataTreeNodeFactory::Pointer factory = mitk::DataTreeNodeFactory::New();

  try
  {
    factory->SetFileName( fileName.c_str() );
    factory->Update();
    mitk::DataTreeNode::Pointer tmpNode = factory->GetOutput( 0 );

    if ( tmpNode.IsNull() )
      return false;

    mitk::Surface::Pointer tmpSurface = dynamic_cast<mitk::Surface*>(tmpNode->GetData());

    if ( tmpSurface )
      SetVtkPolyData( tmpSurface->GetVtkPolyData() );

  }
  catch ( itk::ExceptionObject & ex )
  {
    itkGenericOutputMacro( << "Exception during file open: " << ex );
    return false;
  }

  return true;
}
<commit_msg>FIX:  delete old vtkPolyData in SetVtkPolyData CHG: allow to set NULL as vtkPolyData to explicitly delete one.<commit_after>/*=========================================================================

Program:   Medical Imaging & Interaction Toolkit
Module:    $RCSfile$
Language:  C++
Date:      $Date$
Version:   $Revision$

Copyright (c) German Cancer Research Center, Division of Medical and
Biological Informatics. All rights reserved.
See MITKCopyright.txt or http://www.mitk.org/copyright.html for details.

This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.  See the above copyright notices for more information.

=========================================================================*/

#include "mitkSurface.h"
#include "mitkBaseProcess.h"
#include "vtkPolyData.h"
#include "mitkXMLWriter.h"
#include "mitkXMLReader.h"
#include <vtkPolyDataWriter.h>
//#include <vtkPolyDataReader.h>
#include <vtkSTLWriter.h>
#include "mitkSurfaceVtkWriter.h"
#include "mitkDataTreeNodeFactory.h"
#include <itkSmartPointerForwardReference.txx>

void mitk::Surface::SetVtkPolyData( vtkPolyData* polydata, unsigned int t )
{
  if ( t >= m_PolyDataSeries.size() )
  {
    m_PolyDataSeries.resize( t + 1, NULL );
    Initialize(t+1);
  }
  if(m_PolyDataSeries[ t ] != NULL)
  {
    m_PolyDataSeries[ t ]->Delete();
  }
  m_PolyDataSeries[ t ] = polydata;
  //@todo why do we have to call m_VtkPolyData->Register(NULL?)
  if(m_PolyDataSeries[ t ] != NULL)
  {
    m_PolyDataSeries[ t ]->Register( NULL );
  }
  this->Modified();
  m_CalculateBoundingBox = true;
}

void mitk::Surface::Initialize(unsigned int timeSteps)
{
  mitk::TimeSlicedGeometry::Pointer timeGeometry = this->GetTimeSlicedGeometry();

  mitk::Geometry3D::Pointer g3d = mitk::Geometry3D::New();
  g3d->Initialize();
  mitk::ScalarType timeBounds[] = {0.0, 1.0};
  g3d->SetTimeBounds( timeBounds );
  //
  // The geometry is propagated automatically to the other items,
  // if EvenlyTimed is true...
  //
  timeGeometry->InitializeEvenlyTimed( g3d.GetPointer(), timeSteps );

  vtkPolyData* pdnull = NULL;
  m_PolyDataSeries.reserve(timeSteps);
  m_PolyDataSeries.assign(timeSteps, pdnull);
}

vtkPolyData* mitk::Surface::GetVtkPolyData( unsigned int t )
{

  if ( t < m_PolyDataSeries.size() )
  {
    vtkPolyData* polydata = m_PolyDataSeries[ t ];
    if((polydata==NULL) && (GetSource().GetPointer()!=NULL))
    {
      RegionType requestedregion;
      requestedregion.SetIndex(3, t);
      requestedregion.SetSize(3, 1);
      SetRequestedRegion(&requestedregion);
      GetSource()->Update();
    }
    polydata = m_PolyDataSeries[ t ];
    return polydata;
  }
  else
    return NULL;
}

//##ModelId=3E70F66100C4
mitk::Surface::Surface() : m_CalculateBoundingBox( false )
{

}

//##ModelId=3E70F66100CA
mitk::Surface::~Surface()
{
  for ( VTKPolyDataSeries::iterator it = m_PolyDataSeries.begin(); it != m_PolyDataSeries.end(); ++it )
  {
    if ( ( *it ) != NULL )
      ( *it )->Delete();
  }
  m_PolyDataSeries.clear();
}

//##ModelId=3E70F66100AE
void mitk::Surface::UpdateOutputInformation()
{
  if ( this->GetSource() )
  {
    this->GetSource()->UpdateOutputInformation();
  }
  if ( ( m_CalculateBoundingBox ) && ( m_PolyDataSeries.size() > 0 ) )
    CalculateBoundingBox();
  else
    GetTimeSlicedGeometry()->UpdateInformation();
}

void mitk::Surface::CalculateBoundingBox()
{
  //
  // first make sure, that the associated time sliced geometry has
  // the same number of geometry 3d's as vtkPolyDatas are present
  //
  mitk::TimeSlicedGeometry* timeGeometry = GetTimeSlicedGeometry();
  if ( timeGeometry->GetTimeSteps() != m_PolyDataSeries.size() )
  {
    itkExceptionMacro(<<"timeGeometry->GetTimeSteps() != m_PolyDataSeries.size() -- use Initialize(timeSteps) with correct number of timeSteps!");
  }

  //
  // Iterate over the vtkPolyDatas and update the Geometry
  // information of each of the items.
  //
  for ( unsigned int i = 0 ; i < m_PolyDataSeries.size() ; ++i )
  {
    vtkPolyData* polyData = m_PolyDataSeries[ i ];
    vtkFloatingPointType bounds[ ] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
    if ( ( polyData != NULL ) && ( polyData->GetNumberOfPoints() > 0 ) )
    {
      polyData->Update();
      polyData->ComputeBounds();
      polyData->GetBounds( bounds );
    }
    mitk::Geometry3D::Pointer g3d = timeGeometry->GetGeometry3D( i );
    assert( g3d.IsNotNull() );
    g3d->SetFloatBounds( bounds );
  }
  timeGeometry->UpdateInformation();

  mitk::BoundingBox::Pointer bb = const_cast<mitk::BoundingBox*>( timeGeometry->GetBoundingBox() );
  itkDebugMacro( << "boundingbox min: "<< bb->GetMinimum());
  itkDebugMacro( << "boundingbox max: "<< bb->GetMaximum());
  m_CalculateBoundingBox = false;
}

//##ModelId=3E70F66100B0
void mitk::Surface::SetRequestedRegionToLargestPossibleRegion()
{
  m_RequestedRegion = GetLargestPossibleRegion();
}

//##ModelId=3E70F66100B6

bool mitk::Surface::RequestedRegionIsOutsideOfTheBufferedRegion()
{
  RegionType::IndexValueType end = m_RequestedRegion.GetIndex(3)+m_RequestedRegion.GetSize(3);

  if(((RegionType::IndexValueType)m_PolyDataSeries.size())<end)
    return true;

  for( RegionType::IndexValueType t=m_RequestedRegion.GetIndex(3); t<end; ++t )
    if(m_PolyDataSeries[t]==NULL)
      return true;

  return false;
}

//##ModelId=3E70F66100B8
bool mitk::Surface::VerifyRequestedRegion()
{
  if( (m_RequestedRegion.GetIndex(3)>=0) &&
      (m_RequestedRegion.GetIndex(3)+m_RequestedRegion.GetSize(3)<=m_PolyDataSeries.size()) )
    return true;

  return false;
}

//##ModelId=3E70F66100BA
void mitk::Surface::SetRequestedRegion( itk::DataObject *data )
{
  mitk::Surface *surfaceData;

  surfaceData = dynamic_cast<mitk::Surface*>(data);

  if (surfaceData)
  {
    m_RequestedRegion = surfaceData->GetRequestedRegion();
  }
  else
  {
    // pointer could not be cast back down
    itkExceptionMacro( << "mitk::Surface::SetRequestedRegion(DataObject*) cannot cast " << typeid(data).name() << " to " << typeid(Surface*).name() );
  }
}

void mitk::Surface::SetRequestedRegion(Surface::RegionType *region)  //by arin
{
  if(region!=NULL)
  {
    m_RequestedRegion = *region;
  }
  else
  {
    // pointer could not be cast back down
    itkExceptionMacro( << "mitk::Surface::SetRequestedRegion(Surface::RegionType*) cannot cast " << typeid(region).name() << " to " << typeid(Surface*).name() );
  }
}

//##ModelId=3E70F66100C1

void mitk::Surface::CopyInformation( const itk::DataObject * )
{}

void mitk::Surface::Update()
{
  if ( GetSource() == NULL )
  {
    for ( VTKPolyDataSeries::iterator it = m_PolyDataSeries.begin() ; it != m_PolyDataSeries.end() ; ++it )
    {
      if ( ( *it ) != NULL )
        ( *it )->Update();
    }
  }
  Superclass::Update();
}

void mitk::Surface::Resize( unsigned int timeSteps )
{
  m_PolyDataSeries.resize( timeSteps, NULL );
  this->Modified();
  m_CalculateBoundingBox = true;
}

bool mitk::Surface::WriteXMLData( XMLWriter& xmlWriter )
{
  BaseData::WriteXMLData( xmlWriter );
  std::string fileName = xmlWriter.GetRelativePath();

  if(xmlWriter.IsFileExtension(".vtk", fileName))
  {
    xmlWriter.WriteProperty( XMLReader::FILENAME, fileName.c_str() );

    if(xmlWriter.SaveSourceFiles()){
      mitk::SurfaceVtkWriter<vtkPolyDataWriter>::Pointer writer = mitk::SurfaceVtkWriter<vtkPolyDataWriter>::New();
      writer->SetInput( this );
      fileName = xmlWriter.GetAbsolutePath();
      if(!xmlWriter.IsFileExtension(".vtk", fileName))
        fileName += ".vtk";
      writer->SetFileName( fileName.c_str() );
      writer->Write();
    }
  }
  else
  {
    if(!xmlWriter.IsFileExtension(".stl", fileName))
      fileName += ".stl";
    xmlWriter.WriteProperty( XMLReader::FILENAME, fileName.c_str() );

    if(xmlWriter.SaveSourceFiles()){
      mitk::SurfaceVtkWriter<vtkSTLWriter>::Pointer writer = mitk::SurfaceVtkWriter<vtkSTLWriter>::New();
      writer->SetInput( this );
      fileName = xmlWriter.GetAbsolutePath();
      if(!xmlWriter.IsFileExtension(".stl", fileName))
        fileName += ".stl";
      writer->SetFileName( fileName.c_str() );
      writer->Write();
    }
  }
  return true;
}

bool mitk::Surface::ReadXMLData( XMLReader& xmlReader )
{
  BaseData::ReadXMLData( xmlReader );
  std::string fileName;
  xmlReader.GetAttribute( XMLReader::FILENAME, fileName );

  std::cout << fileName << std::endl;

  mitk::DataTreeNodeFactory::Pointer factory = mitk::DataTreeNodeFactory::New();

  try
  {
    factory->SetFileName( fileName.c_str() );
    factory->Update();
    mitk::DataTreeNode::Pointer tmpNode = factory->GetOutput( 0 );

    if ( tmpNode.IsNull() )
      return false;

    mitk::Surface::Pointer tmpSurface = dynamic_cast<mitk::Surface*>(tmpNode->GetData());

    if ( tmpSurface )
      SetVtkPolyData( tmpSurface->GetVtkPolyData() );

  }
  catch ( itk::ExceptionObject & ex )
  {
    itkGenericOutputMacro( << "Exception during file open: " << ex );
    return false;
  }

  return true;
}
<|endoftext|>


<commit_before><commit_msg>gltf_baker: add UV visualization option<commit_after><|endoftext|>


<commit_before>
#include "luiText.h"
#include "pandaVersion.h"

TypeHandle LUIText::_type_handle;

LUIText::LUIText(PyObject* self, LUIObject* parent, const wstring& text,
                 const string& font_name, float font_size, float x, float y, bool wordwrap)
  :
  LUIObject(self, parent, x, y, parent->get_parent_width(), parent->get_parent_width()),
  _text(text),
  _font_size(font_size),
  _wordwrap(wordwrap) {
  set_font(font_name);
}

LUIText::~LUIText() {

}

void LUIText::update_text() {
  int len = _text.size();

  nassertv(_font != NULL);

  if (lui_cat.is_spam()) {
    lui_cat.spam() << "Current text is '" << _text.c_str() << "'" << endl;
  }

  // Remove all sprites which aren't required
  while (_children.size() > len) {
    if (lui_cat.is_spam()) {
      lui_cat.spam() << "Removing sprite .. " << endl;
    }
    remove_child(*_children.begin());
  }

  // Allocate as many sprites as required
  int to_allocate  = len - _children.size();
  for (int i = 0; i < to_allocate; ++i) {
    if (lui_cat.is_spam()) {
      lui_cat.spam() << "Allocating sprite .. " << endl;
    }
    PT(LUISprite) sprite = new LUISprite(this);

    // Required for smooth text rendering
    sprite->set_snap_position(false);
  }

  // Pixels per unit, used to convert betweeen coordinate spaces
  float ppu = _font_size;
  float line_height = _font->get_line_height();

  vector<int> line_breaks = get_line_breaks();

  // Unreference all current glyphs
  _glyphs.clear();

  // Iterate over the sprites
  int char_idx = 0;
  float current_x_pos = 0.0f;
  float current_y_pos = 0.0f;

  for (auto it = _children.begin(); it != _children.end(); ++it, ++char_idx)
  {
    LUIBaseElement* child = *it;
    LUISprite* sprite = DCAST(LUISprite, child);

    // A lui text should have only sprites contained, otherwise something went wrong
    nassertv(sprite != NULL);

    int char_code = (int)_text.at(char_idx);

#if PANDA_MAJOR_VERSION > 1 || PANDA_MINOR_VERSION >= 10
    CPT(TextGlyph) const_glyph;
#else
    const TextGlyph* const_glyph;
#endif

    // Newline
    if (_wordwrap == TRUE && char_code == 10) {
      current_x_pos = 0;
      current_y_pos += floor(line_height * ppu);
      continue;
    }

    if (_wordwrap == TRUE) {
      if(find(line_breaks.begin(), line_breaks.end(), char_idx) != line_breaks.end()) {
        current_x_pos = 0;
        current_y_pos += floor(line_height * ppu);
      }
    }

    if (!_font->get_glyph(char_code, const_glyph)) {
      sprite->set_texture((Texture*)NULL);
      lui_cat.error() << "Font does not support character with char code " << char_code << ", ignoring .. target = " << _debug_name << endl;
      continue;
    }

    CPT(DynamicTextGlyph) dynamic_glyph = DCAST(DynamicTextGlyph, const_glyph);

    // If this gets executed, a non-dynamic font got loaded.
    nassertv(dynamic_glyph != NULL);

    _glyphs.push_back(dynamic_glyph);

    // Some characters have no texture (like space)
    if (dynamic_glyph->get_page() == NULL) {
      lui_cat.debug() << "Character '" << (char)char_code << "' (Code: " << char_code << ") has no texture page!" << endl;
      sprite->hide();

    } else {
      sprite->show();

      // LUISprite has a check if the texture is the same, so if the atlas didn't
      // change, this is quite efficient.
      sprite->set_texture(dynamic_glyph->get_page());

      // Position the glyph.
      sprite->set_pos(
        current_x_pos + dynamic_glyph->get_left() * ppu,
        (0.85 - dynamic_glyph->get_top()) * ppu + 1 + current_y_pos);

      // The V coordinate is inverted, as panda stores the textures flipped
      sprite->set_uv_range(
        dynamic_glyph->get_uv_left(),
        1 - dynamic_glyph->get_uv_top(),
        dynamic_glyph->get_uv_right(),
        1 - dynamic_glyph->get_uv_bottom());

      // Determine size from coordinates
      sprite->set_size(
         (dynamic_glyph->get_right() - dynamic_glyph->get_left()) * ppu,
         (dynamic_glyph->get_top() - dynamic_glyph->get_bottom()) * ppu);

      sprite->set_color(_color);
    }

    // Break word wrapping
    if (_wordwrap == TRUE && current_x_pos + dynamic_glyph->get_advance() * ppu > get_parent_width()) {
      // glyph length longer then width, force to next line
      current_x_pos = 0;
      current_y_pos += floor(line_height * ppu);
    }
    else {

      // Trim left
      if(_wordwrap == TRUE && current_x_pos == 0 && dynamic_glyph->get_page() == NULL) {
        continue;
      }

      // Move *cursor* by glyph length
      current_x_pos += dynamic_glyph->get_advance() * ppu;

    }

  }

  if (_wordwrap == TRUE) {
    set_size( get_parent_width(), floor(current_y_pos + line_height * ppu));
  }
  else {
    set_size( floor(current_x_pos), floor(line_height * ppu));
  }
}

void LUIText::ls(int indent) {
  cout << string(indent, ' ')  << "[" << _debug_name << "] pos = " << get_abs_pos().get_x() << ", " << get_abs_pos().get_y()
       << "; size = " << get_width() << " x " << get_height() << "; text = u'" << _text << "'; color = "
       << _color << " / " << _composed_color << "; z = " << _z_offset << endl;
}

int LUIText::get_char_index(float pos) const {
  if (lui_cat.is_spam()) {
    lui_cat.spam() << "Trying to resolve " << pos << " into a character index .." << endl;
  }
  nassertr(_font != NULL, 0);

  float cursor = 0.0f;

  for (int i = 0; i < _text.size(); ++i) {
    int char_code = (int)_text.at(i);

#if PANDA_MAJOR_VERSION > 1 || PANDA_MINOR_VERSION >= 10
    CPT(TextGlyph) glyph;
#else
    const TextGlyph* glyph;
#endif
    if (!_font->get_glyph(char_code, glyph)) {
      lui_cat.error() << "Font does not support character with char code " << char_code << ", ignoring .. target = " << _debug_name << endl;
      continue;
    }

    nassertr(glyph != NULL, 0);
    cursor += glyph->get_advance() * _font_size;

    if (cursor > pos) {
      return i;
    }
  }
  return _text.size();
}

float LUIText::get_char_pos(int char_index) const {
  if (lui_cat.is_spam()) {
    lui_cat.spam() << "Trying to resolve " << char_index << " into a character position .." << endl;
  }
  nassertr(_font != NULL, 0);

  // Make sure we don't iterate over the text bounds
  int iterate_max = min(char_index, (int)_text.size());

  float cursor = 0.0f;

  for (int i = 0; i < iterate_max; i++) {
    int char_code = (int)_text.at(i);

#if PANDA_MAJOR_VERSION > 1 || PANDA_MINOR_VERSION >= 10
    CPT(TextGlyph) glyph;
#else
    const TextGlyph* glyph;
#endif
    if (!_font->get_glyph(char_code, glyph)) {
      lui_cat.error() << "Font does not support character with char code " << char_code << ", ignoring .. target = " << _debug_name << endl;
      continue;
    }
    nassertr(glyph != NULL, 0);
    cursor += glyph->get_advance() * _font_size;
  }

  return cursor;
}

// Returns a list of character indexes where linebreaks should occur when wrapping.
vector<int> LUIText::get_line_breaks() {

  vector<int> result;

  if(_wordwrap == TRUE) {

    // Unreference all current glyphs
    _glyphs.clear();

    int char_idx = 0;
    int word_start = 0;
    float word_start_pos = 0.0f;
    float future_x_pos = 0.0f;
    float line_start = 0.0f;
    float ppu = _font_size;

    for (auto it = _children.begin(); it != _children.end(); ++it, ++char_idx)
    {
      LUIBaseElement* child = *it;
      LUISprite* sprite = DCAST(LUISprite, child);

      // A lui text should have only sprites contained, otherwise something went wrong
      nassertr(sprite != NULL, result);

      int char_code = (int)_text.at(char_idx);

#if PANDA_MAJOR_VERSION > 1 || PANDA_MINOR_VERSION >= 10
    CPT(TextGlyph) const_glyph;
#else
    const TextGlyph* const_glyph;
#endif

      // Character is a newline, so lets include this in our list.
      if (char_code == 10) {
        result.push_back(char_idx);
        word_start = char_idx;
        word_start_pos = future_x_pos;
        line_start = future_x_pos;
        continue;
      }

      if (!_font->get_glyph(char_code, const_glyph)) {
        sprite->set_texture((Texture*)NULL);
        lui_cat.error() << "Font does not support character with char code " << char_code << ", ignoring .. target = " << _debug_name << endl;
        continue;
      }

      CPT(DynamicTextGlyph) dynamic_glyph = DCAST(DynamicTextGlyph, const_glyph);

      // If this gets executed, a non-dynamic font got loaded.
      nassertr(dynamic_glyph != NULL, result);

      _glyphs.push_back(dynamic_glyph);

      // If a space, lets mark this as the start of the word.
      if (dynamic_glyph->get_page() == NULL) {
        word_start = char_idx;
        word_start_pos = future_x_pos + dynamic_glyph->get_advance() * ppu;
      }

      // If adding the glyph to the current position on this line will force it over
      // the width of the label, put a new line at the start of the word.
      if (((future_x_pos - line_start) + (dynamic_glyph->get_advance() * ppu))  > get_parent_width()) {
        result.push_back(word_start);
        // After the newline is added, we update the current lines start position.
        line_start = word_start_pos;
      }

      // Move the cursor along by the glyph's width.
      future_x_pos += dynamic_glyph->get_advance() * ppu;

    }

  }

  return result;

}
<commit_msg>Fix compilation error on Linux<commit_after>
#include "luiText.h"
#include "pandaVersion.h"

TypeHandle LUIText::_type_handle;

LUIText::LUIText(PyObject* self, LUIObject* parent, const wstring& text,
                 const string& font_name, float font_size, float x, float y, bool wordwrap)
  :
  LUIObject(self, parent, x, y, parent->get_parent_width(), parent->get_parent_width()),
  _text(text),
  _font_size(font_size),
  _wordwrap(wordwrap) {
  set_font(font_name);
}

LUIText::~LUIText() {

}

void LUIText::update_text() {
  int len = _text.size();

  nassertv(_font != NULL);

  if (lui_cat.is_spam()) {
    lui_cat.spam() << "Current text is '" << _text.c_str() << "'" << endl;
  }

  // Remove all sprites which aren't required
  while (_children.size() > len) {
    if (lui_cat.is_spam()) {
      lui_cat.spam() << "Removing sprite .. " << endl;
    }
    remove_child(*_children.begin());
  }

  // Allocate as many sprites as required
  int to_allocate  = len - _children.size();
  for (int i = 0; i < to_allocate; ++i) {
    if (lui_cat.is_spam()) {
      lui_cat.spam() << "Allocating sprite .. " << endl;
    }
    PT(LUISprite) sprite = new LUISprite(this);

    // Required for smooth text rendering
    sprite->set_snap_position(false);
  }

  // Pixels per unit, used to convert betweeen coordinate spaces
  float ppu = _font_size;
  float line_height = _font->get_line_height();

  vector<int> line_breaks = get_line_breaks();

  // Unreference all current glyphs
  _glyphs.clear();

  // Iterate over the sprites
  int char_idx = 0;
  float current_x_pos = 0.0f;
  float current_y_pos = 0.0f;

  for (auto it = _children.begin(); it != _children.end(); ++it, ++char_idx)
  {
    LUIBaseElement* child = *it;
    LUISprite* sprite = DCAST(LUISprite, child);

    // A lui text should have only sprites contained, otherwise something went wrong
    nassertv(sprite != NULL);

    int char_code = (int)_text.at(char_idx);

#if PANDA_MAJOR_VERSION > 1 || PANDA_MINOR_VERSION >= 10
    CPT(TextGlyph) const_glyph;
#else
    const TextGlyph* const_glyph;
#endif

    // Newline
    if (_wordwrap && char_code == 10) {
      current_x_pos = 0;
      current_y_pos += floor(line_height * ppu);
      continue;
    }

    if (_wordwrap) {
      if(find(line_breaks.begin(), line_breaks.end(), char_idx) != line_breaks.end()) {
        current_x_pos = 0;
        current_y_pos += floor(line_height * ppu);
      }
    }

    if (!_font->get_glyph(char_code, const_glyph)) {
      sprite->set_texture((Texture*)NULL);
      lui_cat.error() << "Font does not support character with char code " << char_code << ", ignoring .. target = " << _debug_name << endl;
      continue;
    }

    CPT(DynamicTextGlyph) dynamic_glyph = DCAST(DynamicTextGlyph, const_glyph);

    // If this gets executed, a non-dynamic font got loaded.
    nassertv(dynamic_glyph != NULL);

    _glyphs.push_back(dynamic_glyph);

    // Some characters have no texture (like space)
    if (dynamic_glyph->get_page() == NULL) {
      lui_cat.debug() << "Character '" << (char)char_code << "' (Code: " << char_code << ") has no texture page!" << endl;
      sprite->hide();

    } else {
      sprite->show();

      // LUISprite has a check if the texture is the same, so if the atlas didn't
      // change, this is quite efficient.
      sprite->set_texture(dynamic_glyph->get_page());

      // Position the glyph.
      sprite->set_pos(
        current_x_pos + dynamic_glyph->get_left() * ppu,
        (0.85 - dynamic_glyph->get_top()) * ppu + 1 + current_y_pos);

      // The V coordinate is inverted, as panda stores the textures flipped
      sprite->set_uv_range(
        dynamic_glyph->get_uv_left(),
        1 - dynamic_glyph->get_uv_top(),
        dynamic_glyph->get_uv_right(),
        1 - dynamic_glyph->get_uv_bottom());

      // Determine size from coordinates
      sprite->set_size(
         (dynamic_glyph->get_right() - dynamic_glyph->get_left()) * ppu,
         (dynamic_glyph->get_top() - dynamic_glyph->get_bottom()) * ppu);

      sprite->set_color(_color);
    }

    // Break word wrapping
    if (_wordwrap && current_x_pos + dynamic_glyph->get_advance() * ppu > get_parent_width()) {
      // glyph length longer then width, force to next line
      current_x_pos = 0;
      current_y_pos += floor(line_height * ppu);
    }
    else {

      // Trim left
      if (_wordwrap && current_x_pos == 0 && dynamic_glyph->get_page() == NULL) {
        continue;
      }

      // Move *cursor* by glyph length
      current_x_pos += dynamic_glyph->get_advance() * ppu;

    }

  }

  if (_wordwrap) {
    set_size( get_parent_width(), floor(current_y_pos + line_height * ppu));
  }
  else {
    set_size( floor(current_x_pos), floor(line_height * ppu));
  }
}

void LUIText::ls(int indent) {
  cout << string(indent, ' ')  << "[" << _debug_name << "] pos = " << get_abs_pos().get_x() << ", " << get_abs_pos().get_y()
       << "; size = " << get_width() << " x " << get_height() << "; text = u'" << _text << "'; color = "
       << _color << " / " << _composed_color << "; z = " << _z_offset << endl;
}

int LUIText::get_char_index(float pos) const {
  if (lui_cat.is_spam()) {
    lui_cat.spam() << "Trying to resolve " << pos << " into a character index .." << endl;
  }
  nassertr(_font != NULL, 0);

  float cursor = 0.0f;

  for (int i = 0; i < _text.size(); ++i) {
    int char_code = (int)_text.at(i);

#if PANDA_MAJOR_VERSION > 1 || PANDA_MINOR_VERSION >= 10
    CPT(TextGlyph) glyph;
#else
    const TextGlyph* glyph;
#endif
    if (!_font->get_glyph(char_code, glyph)) {
      lui_cat.error() << "Font does not support character with char code " << char_code << ", ignoring .. target = " << _debug_name << endl;
      continue;
    }

    nassertr(glyph != NULL, 0);
    cursor += glyph->get_advance() * _font_size;

    if (cursor > pos) {
      return i;
    }
  }
  return _text.size();
}

float LUIText::get_char_pos(int char_index) const {
  if (lui_cat.is_spam()) {
    lui_cat.spam() << "Trying to resolve " << char_index << " into a character position .." << endl;
  }
  nassertr(_font != NULL, 0);

  // Make sure we don't iterate over the text bounds
  int iterate_max = min(char_index, (int)_text.size());

  float cursor = 0.0f;

  for (int i = 0; i < iterate_max; i++) {
    int char_code = (int)_text.at(i);

#if PANDA_MAJOR_VERSION > 1 || PANDA_MINOR_VERSION >= 10
    CPT(TextGlyph) glyph;
#else
    const TextGlyph* glyph;
#endif
    if (!_font->get_glyph(char_code, glyph)) {
      lui_cat.error() << "Font does not support character with char code " << char_code << ", ignoring .. target = " << _debug_name << endl;
      continue;
    }
    nassertr(glyph != NULL, 0);
    cursor += glyph->get_advance() * _font_size;
  }

  return cursor;
}

// Returns a list of character indexes where linebreaks should occur when wrapping.
vector<int> LUIText::get_line_breaks() {

  vector<int> result;

  if (_wordwrap) {

    // Unreference all current glyphs
    _glyphs.clear();

    int char_idx = 0;
    int word_start = 0;
    float word_start_pos = 0.0f;
    float future_x_pos = 0.0f;
    float line_start = 0.0f;
    float ppu = _font_size;

    for (auto it = _children.begin(); it != _children.end(); ++it, ++char_idx)
    {
      LUIBaseElement* child = *it;
      LUISprite* sprite = DCAST(LUISprite, child);

      // A lui text should have only sprites contained, otherwise something went wrong
      nassertr(sprite != NULL, result);

      int char_code = (int)_text.at(char_idx);

#if PANDA_MAJOR_VERSION > 1 || PANDA_MINOR_VERSION >= 10
    CPT(TextGlyph) const_glyph;
#else
    const TextGlyph* const_glyph;
#endif

      // Character is a newline, so lets include this in our list.
      if (char_code == 10) {
        result.push_back(char_idx);
        word_start = char_idx;
        word_start_pos = future_x_pos;
        line_start = future_x_pos;
        continue;
      }

      if (!_font->get_glyph(char_code, const_glyph)) {
        sprite->set_texture((Texture*)NULL);
        lui_cat.error() << "Font does not support character with char code " << char_code << ", ignoring .. target = " << _debug_name << endl;
        continue;
      }

      CPT(DynamicTextGlyph) dynamic_glyph = DCAST(DynamicTextGlyph, const_glyph);

      // If this gets executed, a non-dynamic font got loaded.
      nassertr(dynamic_glyph != NULL, result);

      _glyphs.push_back(dynamic_glyph);

      // If a space, lets mark this as the start of the word.
      if (dynamic_glyph->get_page() == NULL) {
        word_start = char_idx;
        word_start_pos = future_x_pos + dynamic_glyph->get_advance() * ppu;
      }

      // If adding the glyph to the current position on this line will force it over
      // the width of the label, put a new line at the start of the word.
      if (((future_x_pos - line_start) + (dynamic_glyph->get_advance() * ppu))  > get_parent_width()) {
        result.push_back(word_start);
        // After the newline is added, we update the current lines start position.
        line_start = word_start_pos;
      }

      // Move the cursor along by the glyph's width.
      future_x_pos += dynamic_glyph->get_advance() * ppu;

    }

  }

  return result;

}
<|endoftext|>