<commit_before>/**
 * @file device_properties.hxx
 * @author Muhammad Osama (mosama@ucdavis.edu)
 * @brief
 * @version 0.1
 * @date 2020-10-05
 *
 * @copyright Copyright (c) 2020
 *
 */
#pragma once
#include <iostream>
#include <gunrock/cuda/device.hxx>
#include <gunrock/error.hxx>

namespace gunrock {
namespace cuda {

typedef cudaDeviceProp device_properties_t;

typedef struct {
  unsigned major;
  unsigned minor;
  constexpr unsigned as_combined_number() const {
    return major * 10 + minor;
  }
  constexpr bool operator==(int i) { return (int)as_combined_number() == i; }
  constexpr bool operator!=(int i) { return (int)as_combined_number() != i; }
  constexpr bool operator>(int i) { return (int)as_combined_number() > i; }
  constexpr bool operator<(int i) { return (int)as_combined_number() < i; }
  constexpr bool operator>=(int i) { return (int)as_combined_number() >= i; }
  constexpr bool operator<=(int i) { return (int)as_combined_number() <= i; }
} compute_capability_t;

/**
 * @brief Get compute capability from major and minor versions.
 * @param major Compute capability major version
 * @param minor Compute capability minor version
 * \return compute_capability_t
 */
constexpr compute_capability_t make_compute_capability(unsigned major,
                                                       unsigned minor) {
  return compute_capability_t{major, minor};
}

/**
 * @brief Get compute capability from combined major and minor version.
 * @param combined Combined major and minor value, e.g. 86 for 8.6
 * \return compute_capability_t
 */
constexpr compute_capability_t make_compute_capability(unsigned combined) {
  return compute_capability_t{combined / 10, combined % 10};
}
/**
 * @namespace properties
 * C++ based CUDA device properties.
 */
namespace properties {

/**
 * @brief Enums for units used by device property values.
 */
enum : size_t {
  KiB = 1024,
  K   = 1024
};

/**
 * @brief Architecture name based on compute capability.
 * https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#compute-capability
 * @param capability Compute capability from which to get the result
 * \return const char* architecture name or nullptr if capability is invalid
 */
inline constexpr const char* arch_name(compute_capability_t capability) {
  return
    (capability.major == 8) ?  "Ampere" :
    (capability.major == 7 && capability.minor == 5) ? "Turing" :
    (capability.major == 7) ?   "Volta" :
    (capability.major == 6) ?  "Pascal" :
    (capability.major == 5) ? "Maxwell" :
    (capability.major == 3) ?  "Kepler" :
                                nullptr ;
}

// Device properties retrieved from:
// https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#features-and-technical-specifications

/**
 * @brief Maximum number of threads per block.
 * \return unsigned
 */
inline constexpr unsigned cta_max_threads() {
  return 1 << 10;  // 1024 threads per CTA
}

/**
 * @brief Warp size (has always been 32, but is subject to change).
 * \return unsigned
 */
inline constexpr unsigned warp_max_threads() {
  return 1 << 5;
}

/**
 * @brief Maximum number of resident blocks per SM.
 * @param capability Compute capability from which to get the result
 * \return unsigned
 */
inline constexpr unsigned sm_max_ctas(compute_capability_t capability) {
  return
    (capability >= 86) ? 16 :  // SM86+
    (capability >= 80) ? 32 :  // SM80
    (capability >= 75) ? 16 :  // SM75
    (capability >= 50) ? 32 :  // SM50-SM72
                         16 ;  // SM30-SM37
}

/**
 * @brief Maximum number of resident threads per SM.
 * @param capability Compute capability from which to get the result
 * \return unsigned
 */
inline constexpr unsigned sm_max_threads(compute_capability_t capability) {
  return
    (capability >= 86) ? 1536 :  // SM86+
    (capability >= 80) ? 2048 :  // SM80
    (capability >= 75) ? 1024 :  // SM75
                         2048 ;  // SM30-SM72
}

/**
 * @brief Number of 32-bit registers per SM.
 * @param capability Compute capability from which to get the result
 * \return unsigned
 */
inline constexpr unsigned sm_registers(compute_capability_t capability) {
  return
    (capability >= 50) ?  64 * K :  // SM50+
    (capability >= 37) ? 128 * K :  // SM37
                          64 * K ;  // SM30-SM35
}

/**
 * @brief Maximum amount of shared memory per SM.
 * @tparam sm3XCacheConfig cudaFuncCache enum representing the shared data
 *                         cache configuration used when called on compute
 *                         capability 3.x
 * @param capability       Compute capability from which to get the result
 * \return unsigned
 * @todo Test if this function can be resolved at compile time
 */
template<enum cudaFuncCache sm3XCacheConfig = cudaFuncCachePreferNone>
inline constexpr unsigned sm_max_shared_memory_bytes(
  compute_capability_t capability
) {
  unsigned sm3XConfiguredSmem =
    (sm3XCacheConfig == cudaFuncCachePreferNone)   ? 48 * KiB :
    (sm3XCacheConfig == cudaFuncCachePreferShared) ? 48 * KiB :
    (sm3XCacheConfig == cudaFuncCachePreferL1)     ? 16 * KiB :
    (sm3XCacheConfig == cudaFuncCachePreferEqual)  ? 32 * KiB :
                                                     48 * KiB ;

  return
    (capability >= 86) ? 100 * KiB :  // SM86+
    (capability >= 80) ? 164 * KiB :  // SM80
    (capability >= 75) ?  64 * KiB :  // SM75
    (capability >= 70) ?  96 * KiB :  // SM70-SM72
    (capability >= 62) ?  64 * KiB :  // SM62
    (capability >= 61) ?  96 * KiB :  // SM61
    (capability >= 53) ?  64 * KiB :  // SM53
    (capability >= 52) ?  96 * KiB :  // SM52
    (capability >= 50) ?  64 * KiB :  // SM50
    (capability >= 37) ?  64 * KiB + sm3XConfiguredSmem :  // SM37
                sm3XConfiguredSmem ;  // SM30-SM35
}

/**
 * @brief Number of shared memory banks.
 * \return unsigned
 */
inline constexpr unsigned shared_memory_banks() {
  return 1 << 5;  // 32 memory banks per SM
}

/**
 * @brief Stride length (number of bytes per word) of shared memory in bytes.
 * @tparam sm3XSmemConfig cudaSharedMemConfig enum representing the shared
 *                        memory bank size (stride) used when called on compute
 *                        capability 3.x
 * \return unsigned
 */
template<enum cudaSharedMemConfig sm3XSmemConfig = cudaSharedMemBankSizeDefault>
inline constexpr unsigned shared_memory_bank_stride() {
  // The default config on 3.x is the same constant value for later archs
  // Only let 3.x be configurable if stride later becomes dependent on arch
  return
    (sm3XSmemConfig == cudaSharedMemBankSizeDefault)   ? 1 << 2 :
    (sm3XSmemConfig == cudaSharedMemBankSizeFourByte)  ? 1 << 2 :
    (sm3XSmemConfig == cudaSharedMemBankSizeEightByte) ? 1 << 3 :
                                                         1 << 2 ;
}

void print(device_properties_t& prop) {
  device_id_t ordinal;
  cudaGetDevice(&ordinal);

  size_t freeMem, totalMem;
  error::error_t status = cudaMemGetInfo(&freeMem, &totalMem);
  error::throw_if_exception(status);

  double memBandwidth =
      (prop.memoryClockRate * 1000.0) * (prop.memoryBusWidth / 8 * 2) / 1.0e9;

  std::cout << prop.name << " : " << prop.clockRate / 1000.0 << " Mhz "
            << "(Ordinal " << ordinal << ")" << std::endl;
  std::cout << "FreeMem: " << (int)(freeMem / (1 << 20)) << " MB "
            << "TotalMem: " << (int)(totalMem / (1 << 20)) << " MB "
            << ((int)8 * sizeof(int*)) << "-bit pointers." << std::endl;
  std::cout << prop.multiProcessorCount
            << " SMs enabled, Compute Capability sm_" << prop.major
            << prop.minor << std::endl;
  std::cout << "Mem Clock: " << prop.memoryClockRate / 1000.0 << " Mhz x "
            << prop.memoryBusWidth << " bits (" << memBandwidth << " GB/s)"
            << std::endl;
  std::cout << "ECC " << (prop.ECCEnabled ? "Enabled" : "Disabled")
            << std::endl;
}

}  // namespace properties

}  // namespace cuda
}  // namespace gunrock
<commit_msg>Add make_compute_capability()<commit_after>/**
 * @file device_properties.hxx
 * @author Muhammad Osama (mosama@ucdavis.edu)
 * @brief
 * @version 0.1
 * @date 2020-10-05
 *
 * @copyright Copyright (c) 2020
 *
 */
#pragma once
#include <iostream>
#include <gunrock/cuda/device.hxx>
#include <gunrock/error.hxx>

namespace gunrock {
namespace cuda {

typedef cudaDeviceProp device_properties_t;

typedef struct {
  unsigned major;
  unsigned minor;
  constexpr unsigned as_combined_number() const {
    return major * 10 + minor;
  }
  constexpr bool operator==(int i) { return (int)as_combined_number() == i; }
  constexpr bool operator!=(int i) { return (int)as_combined_number() != i; }
  constexpr bool operator>(int i) { return (int)as_combined_number() > i; }
  constexpr bool operator<(int i) { return (int)as_combined_number() < i; }
  constexpr bool operator>=(int i) { return (int)as_combined_number() >= i; }
  constexpr bool operator<=(int i) { return (int)as_combined_number() <= i; }
} compute_capability_t;

/**
 * @brief Make compute capability from major and minor versions.
 * @param major Compute capability major version
 * @param minor Compute capability minor version
 * \return compute_capability_t
 */
constexpr compute_capability_t make_compute_capability(unsigned major,
                                                       unsigned minor) {
  return compute_capability_t{major, minor};
}

/**
 * @brief Make compute capability from combined major and minor version.
 * @param combined Combined major and minor value, e.g. 86 for 8.6
 * \return compute_capability_t
 */
constexpr compute_capability_t make_compute_capability(unsigned combined) {
  return compute_capability_t{combined / 10, combined % 10};
}

/**
 * @brief Get compute capability from SM_TARGET macro.
 * \return compute_capabilty_t
 */
constexpr compute_capability_t get_compute_capability() {
  return make_compute_capability(SM_TARGET);
}

/**
 * @namespace properties
 * C++ based CUDA device properties.
 */
namespace properties {

/**
 * @brief Enums for units used by device property values.
 */
enum : size_t {
  KiB = 1024,
  K   = 1024
};

/**
 * @brief Architecture name based on compute capability.
 * https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#compute-capability
 * @param capability Compute capability from which to get the result
 * \return const char* architecture name or nullptr if capability is invalid
 */
inline constexpr const char* arch_name(compute_capability_t capability) {
  return
    (capability.major == 8) ?  "Ampere" :
    (capability.major == 7 && capability.minor == 5) ? "Turing" :
    (capability.major == 7) ?   "Volta" :
    (capability.major == 6) ?  "Pascal" :
    (capability.major == 5) ? "Maxwell" :
    (capability.major == 3) ?  "Kepler" :
                                nullptr ;
}

// Device properties retrieved from:
// https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#features-and-technical-specifications

/**
 * @brief Maximum number of threads per block.
 * \return unsigned
 */
inline constexpr unsigned cta_max_threads() {
  return 1 << 10;  // 1024 threads per CTA
}

/**
 * @brief Warp size (has always been 32, but is subject to change).
 * \return unsigned
 */
inline constexpr unsigned warp_max_threads() {
  return 1 << 5;
}

/**
 * @brief Maximum number of resident blocks per SM.
 * @param capability Compute capability from which to get the result
 * \return unsigned
 */
inline constexpr unsigned sm_max_ctas(compute_capability_t capability) {
  return
    (capability >= 86) ? 16 :  // SM86+
    (capability >= 80) ? 32 :  // SM80
    (capability >= 75) ? 16 :  // SM75
    (capability >= 50) ? 32 :  // SM50-SM72
                         16 ;  // SM30-SM37
}

/**
 * @brief Maximum number of resident threads per SM.
 * @param capability Compute capability from which to get the result
 * \return unsigned
 */
inline constexpr unsigned sm_max_threads(compute_capability_t capability) {
  return
    (capability >= 86) ? 1536 :  // SM86+
    (capability >= 80) ? 2048 :  // SM80
    (capability >= 75) ? 1024 :  // SM75
                         2048 ;  // SM30-SM72
}

/**
 * @brief Number of 32-bit registers per SM.
 * @param capability Compute capability from which to get the result
 * \return unsigned
 */
inline constexpr unsigned sm_registers(compute_capability_t capability) {
  return
    (capability >= 50) ?  64 * K :  // SM50+
    (capability >= 37) ? 128 * K :  // SM37
                          64 * K ;  // SM30-SM35
}

/**
 * @brief Maximum amount of shared memory per SM.
 * @tparam sm3XCacheConfig cudaFuncCache enum representing the shared data
 *                         cache configuration used when called on compute
 *                         capability 3.x
 * @param capability       Compute capability from which to get the result
 * \return unsigned
 * @todo Test if this function can be resolved at compile time
 */
template<enum cudaFuncCache sm3XCacheConfig = cudaFuncCachePreferNone>
inline constexpr unsigned sm_max_shared_memory_bytes(
  compute_capability_t capability
) {
  unsigned sm3XConfiguredSmem =
    (sm3XCacheConfig == cudaFuncCachePreferNone)   ? 48 * KiB :
    (sm3XCacheConfig == cudaFuncCachePreferShared) ? 48 * KiB :
    (sm3XCacheConfig == cudaFuncCachePreferL1)     ? 16 * KiB :
    (sm3XCacheConfig == cudaFuncCachePreferEqual)  ? 32 * KiB :
                                                     48 * KiB ;

  return
    (capability >= 86) ? 100 * KiB :  // SM86+
    (capability >= 80) ? 164 * KiB :  // SM80
    (capability >= 75) ?  64 * KiB :  // SM75
    (capability >= 70) ?  96 * KiB :  // SM70-SM72
    (capability >= 62) ?  64 * KiB :  // SM62
    (capability >= 61) ?  96 * KiB :  // SM61
    (capability >= 53) ?  64 * KiB :  // SM53
    (capability >= 52) ?  96 * KiB :  // SM52
    (capability >= 50) ?  64 * KiB :  // SM50
    (capability >= 37) ?  64 * KiB + sm3XConfiguredSmem :  // SM37
                sm3XConfiguredSmem ;  // SM30-SM35
}

/**
 * @brief Number of shared memory banks.
 * \return unsigned
 */
inline constexpr unsigned shared_memory_banks() {
  return 1 << 5;  // 32 memory banks per SM
}

/**
 * @brief Stride length (number of bytes per word) of shared memory in bytes.
 * @tparam sm3XSmemConfig cudaSharedMemConfig enum representing the shared
 *                        memory bank size (stride) used when called on compute
 *                        capability 3.x
 * \return unsigned
 */
template<enum cudaSharedMemConfig sm3XSmemConfig = cudaSharedMemBankSizeDefault>
inline constexpr unsigned shared_memory_bank_stride() {
  // The default config on 3.x is the same constant value for later archs
  // Only let 3.x be configurable if stride later becomes dependent on arch
  return
    (sm3XSmemConfig == cudaSharedMemBankSizeDefault)   ? 1 << 2 :
    (sm3XSmemConfig == cudaSharedMemBankSizeFourByte)  ? 1 << 2 :
    (sm3XSmemConfig == cudaSharedMemBankSizeEightByte) ? 1 << 3 :
                                                         1 << 2 ;
}

void print(device_properties_t& prop) {
  device_id_t ordinal;
  cudaGetDevice(&ordinal);

  size_t freeMem, totalMem;
  error::error_t status = cudaMemGetInfo(&freeMem, &totalMem);
  error::throw_if_exception(status);

  double memBandwidth =
      (prop.memoryClockRate * 1000.0) * (prop.memoryBusWidth / 8 * 2) / 1.0e9;

  std::cout << prop.name << " : " << prop.clockRate / 1000.0 << " Mhz "
            << "(Ordinal " << ordinal << ")" << std::endl;
  std::cout << "FreeMem: " << (int)(freeMem / (1 << 20)) << " MB "
            << "TotalMem: " << (int)(totalMem / (1 << 20)) << " MB "
            << ((int)8 * sizeof(int*)) << "-bit pointers." << std::endl;
  std::cout << prop.multiProcessorCount
            << " SMs enabled, Compute Capability sm_" << prop.major
            << prop.minor << std::endl;
  std::cout << "Mem Clock: " << prop.memoryClockRate / 1000.0 << " Mhz x "
            << prop.memoryBusWidth << " bits (" << memBandwidth << " GB/s)"
            << std::endl;
  std::cout << "ECC " << (prop.ECCEnabled ? "Enabled" : "Disabled")
            << std::endl;
}

}  // namespace properties

}  // namespace cuda
}  // namespace gunrock
<|endoftext|>


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

#ifndef _BASEDLGS_HXX //autogen
#include <sfx2/basedlgs.hxx>
#endif
#ifndef _SFXTABDLG_HXX //autogen
#include <sfx2/tabdlg.hxx>
#endif
#ifndef _SVTREEBOX_HXX //autogen
#include <svtools/svtreebx.hxx>
#endif
#ifndef _TOOLS_RESARY_HXX
#include <tools/resary.hxx>
#endif
#ifndef _SV_IMAGE_HXX //autogen
#include <vcl/image.hxx>
#endif
#ifndef _SV_FIXBRD_HXX //autogen
#include <vcl/fixbrd.hxx>
#endif

#define NUMBER_OF_OPTION_PAGES  12
class SfxModule;
class SfxShell;
struct OptionsPageInfo;

class OfaOptionsTreeListBox : public SvTreeListBox
{
private:
    BOOL            bInCollapse;

public:
    OfaOptionsTreeListBox(Window* pParent, const ResId& rResId) :
        SvTreeListBox( pParent, rResId ), bInCollapse(FALSE) {}

    virtual BOOL    Collapse( SvLBoxEntry* pParent );
    BOOL            IsInCollapse()const {return bInCollapse;}
};

BOOL            EnableSSO();
void*           GetSSOCreator( void );

/* -----------------11.02.99 07:51-------------------
 *
 * --------------------------------------------------*/
class OfaTreeOptionsDialog : public SfxModalDialog
{
private:
    OKButton        aOkPB;
    CancelButton    aCancelPB;
    HelpButton      aHelpPB;
    PushButton      aBackPB;

    FixedBorder     aHiddenGB;
    FixedText       aPageTitleFT;
    FixedLine       aLine1FL;
    FixedText       aHelpFT;
    FixedImage      aHelpImg;

    ImageList       aPageImages;
    ImageList       aPageImagesHC;

    ResStringArray  aHelpTextsArr;

    OfaOptionsTreeListBox   aTreeLB;

    String          sTitle;
    String          sHintTitle;
    String          sNotLoadedError;

    const OptionsPageInfo*  pHintInfo;
    SvLBoxEntry*            pCurrentPageEntry;

    // for the ColorTabPage
    SfxItemSet*     pColorPageItemSet;
    XColorTable*    pColorTab;
    USHORT          nChangeType;
    USHORT          nUnknownType;
    USHORT          nUnknownPos;
    BOOL            bIsAreaTP;

    BOOL            bForgetSelection;
    BOOL            bExternBrowserActive;
    BOOL            bImageResized;
    bool            bInSelectHdl_Impl;

    Timer           aHintTimer;
    Timer           aSelectTimer;

    static USHORT   nLastDialogPageId;

    void            StartHint( const OptionsPageInfo* pInfo, const XubString& rTitle );
    void            ShowHint();
    SfxItemSet*     CreateItemSet( USHORT nId );
    void            ApplyItemSet( USHORT nId, const SfxItemSet& rSet );
    void            Initialize();
    void            ResizeTreeLB( void );   // resizes dialog so that treelistbox has no horizontal scroll bar

protected:
        DECL_LINK(ExpandedHdl_Impl, SvTreeListBox* );
        DECL_LINK(ShowPageHdl_Impl, SvTreeListBox* );
        DECL_LINK(BackHdl_Impl, PushButton* );
        DECL_LINK( OKHdl_Impl, Button * );
        DECL_LINK( HintHdl_Impl, Timer * );
        DECL_LINK( SelectHdl_Impl, Timer * );

        virtual long    Notify( NotifyEvent& rNEvt );
        virtual void    DataChanged( const DataChangedEvent& rDCEvt );
        virtual short   Execute();

public:
        OfaTreeOptionsDialog(Window* pParent);
        ~OfaTreeOptionsDialog();

        void    AddTabPage( USHORT nId, const String& rPageName, USHORT nGroup);
        USHORT  AddGroup(const String& rGroupName,  SfxShell* pCreateShell,
                                    SfxModule* pCreateModule, USHORT nDialogId);
        void    ActivateLastSelection();
        void    ActivatePage(USHORT nResId);
        void    ApplyItemSets();

    USHORT                  GetColorChanged() const { return nChangeType; }
    XColorTable*            GetColorTable() { return pColorTab; }
};
/* -----------------11.02.99 15:49-------------------
 *
 * --------------------------------------------------*/
class OfaPageResource : public Resource
{
    ResStringArray      aGeneralDlgAry;
    ResStringArray      aInetDlgAry;
    ResStringArray      aLangDlgAry;
    ResStringArray      aTextDlgAry;
    ResStringArray      aHTMLDlgAry;
    ResStringArray      aCalcDlgAry;
    ResStringArray      aStarMathDlgAry;
    ResStringArray      aImpressDlgAry;
    ResStringArray      aDrawDlgAry;
    ResStringArray      aChartDlgAry;
    ResStringArray      aFilterDlgAry;
    ResStringArray      aDatasourcesDlgAry;

public:
    OfaPageResource();

    ResStringArray& GetGeneralArray()       {return aGeneralDlgAry;}
    ResStringArray& GetInetArray()          {return aInetDlgAry;}
    ResStringArray& GetLangArray()          {return aLangDlgAry;}
    ResStringArray& GetTextArray()          {return aTextDlgAry;}
    ResStringArray& GetHTMLArray()          {return aHTMLDlgAry;}
    ResStringArray& GetCalcArray()          {return aCalcDlgAry;}
    ResStringArray& GetStarMathArray()      {return aStarMathDlgAry;}
    ResStringArray& GetImpressArray()       {return aImpressDlgAry;}
    ResStringArray& GetDrawArray()          {return aDrawDlgAry;}
    ResStringArray& GetChartArray()         {return aChartDlgAry;}
    ResStringArray& GetFilterArray()        {return aFilterDlgAry;}
    ResStringArray& GetDatasourcesArray()   {return aDatasourcesDlgAry;}
};

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

#ifndef _BASEDLGS_HXX //autogen
#include <sfx2/basedlgs.hxx>
#endif
#ifndef _SFXTABDLG_HXX //autogen
#include <sfx2/tabdlg.hxx>
#endif
#ifndef _SVTREEBOX_HXX //autogen
#include <svtools/svtreebx.hxx>
#endif
#ifndef _TOOLS_RESARY_HXX
#include <tools/resary.hxx>
#endif
#ifndef _SV_IMAGE_HXX //autogen
#include <vcl/image.hxx>
#endif
#ifndef _SV_FIXBRD_HXX //autogen
#include <vcl/fixbrd.hxx>
#endif

#define NUMBER_OF_OPTION_PAGES  12
class SfxModule;
class SfxShell;

class OfaOptionsTreeListBox : public SvTreeListBox
{
private:
    BOOL            bInCollapse;

public:
    OfaOptionsTreeListBox(Window* pParent, const ResId& rResId) :
        SvTreeListBox( pParent, rResId ), bInCollapse(FALSE) {}

    virtual BOOL    Collapse( SvLBoxEntry* pParent );
    BOOL            IsInCollapse()const {return bInCollapse;}
};

BOOL            EnableSSO();
void*           GetSSOCreator( void );

/* -----------------11.02.99 07:51-------------------
 *
 * --------------------------------------------------*/
class OfaTreeOptionsDialog : public SfxModalDialog
{
private:
    OKButton        aOkPB;
    CancelButton    aCancelPB;
    HelpButton      aHelpPB;
    PushButton      aBackPB;

    FixedBorder     aHiddenGB;
    FixedText       aPageTitleFT;
    FixedLine       aLine1FL;
    FixedText       aHelpFT;
    FixedImage      aHelpImg;

    ImageList       aPageImages;
    ImageList       aPageImagesHC;

    ResStringArray  aHelpTextsArr;

    OfaOptionsTreeListBox   aTreeLB;

    String          sTitle;
    String          sNotLoadedError;

    SvLBoxEntry*            pCurrentPageEntry;

    // for the ColorTabPage
    SfxItemSet*     pColorPageItemSet;
    XColorTable*    pColorTab;
    USHORT          nChangeType;
    USHORT          nUnknownType;
    USHORT          nUnknownPos;
    BOOL            bIsAreaTP;

    BOOL            bForgetSelection;
    BOOL            bExternBrowserActive;
    BOOL            bImageResized;
    bool            bInSelectHdl_Impl;

    Timer           aSelectTimer;

    static USHORT   nLastDialogPageId;

    SfxItemSet*     CreateItemSet( USHORT nId );
    void            ApplyItemSet( USHORT nId, const SfxItemSet& rSet );
    void            Initialize();
    void            ResizeTreeLB( void );   // resizes dialog so that treelistbox has no horizontal scroll bar

protected:
        DECL_LINK(ExpandedHdl_Impl, SvTreeListBox* );
        DECL_LINK(ShowPageHdl_Impl, SvTreeListBox* );
        DECL_LINK(BackHdl_Impl, PushButton* );
        DECL_LINK( OKHdl_Impl, Button * );
        DECL_LINK( HintHdl_Impl, Timer * );
        DECL_LINK( SelectHdl_Impl, Timer * );

        virtual long    Notify( NotifyEvent& rNEvt );
        virtual void    DataChanged( const DataChangedEvent& rDCEvt );
        virtual short   Execute();

public:
        OfaTreeOptionsDialog(Window* pParent);
        ~OfaTreeOptionsDialog();

        void    AddTabPage( USHORT nId, const String& rPageName, USHORT nGroup);
        USHORT  AddGroup(const String& rGroupName,  SfxShell* pCreateShell,
                                    SfxModule* pCreateModule, USHORT nDialogId);
        void    ActivateLastSelection();
        void    ActivatePage(USHORT nResId);
        void    ApplyItemSets();

    USHORT                  GetColorChanged() const { return nChangeType; }
    XColorTable*            GetColorTable() { return pColorTab; }
};
/* -----------------11.02.99 15:49-------------------
 *
 * --------------------------------------------------*/
class OfaPageResource : public Resource
{
    ResStringArray      aGeneralDlgAry;
    ResStringArray      aInetDlgAry;
    ResStringArray      aLangDlgAry;
    ResStringArray      aTextDlgAry;
    ResStringArray      aHTMLDlgAry;
    ResStringArray      aCalcDlgAry;
    ResStringArray      aStarMathDlgAry;
    ResStringArray      aImpressDlgAry;
    ResStringArray      aDrawDlgAry;
    ResStringArray      aChartDlgAry;
    ResStringArray      aFilterDlgAry;
    ResStringArray      aDatasourcesDlgAry;

public:
    OfaPageResource();

    ResStringArray& GetGeneralArray()       {return aGeneralDlgAry;}
    ResStringArray& GetInetArray()          {return aInetDlgAry;}
    ResStringArray& GetLangArray()          {return aLangDlgAry;}
    ResStringArray& GetTextArray()          {return aTextDlgAry;}
    ResStringArray& GetHTMLArray()          {return aHTMLDlgAry;}
    ResStringArray& GetCalcArray()          {return aCalcDlgAry;}
    ResStringArray& GetStarMathArray()      {return aStarMathDlgAry;}
    ResStringArray& GetImpressArray()       {return aImpressDlgAry;}
    ResStringArray& GetDrawArray()          {return aDrawDlgAry;}
    ResStringArray& GetChartArray()         {return aChartDlgAry;}
    ResStringArray& GetFilterArray()        {return aFilterDlgAry;}
    ResStringArray& GetDatasourcesArray()   {return aDatasourcesDlgAry;}
};

<|endoftext|>


<commit_before>// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "anim_pipeline.h"

#include "anim_generated.h"
#include "fplutil/file_utils.h"
#include "motive/math/angle.h"

using fplutil::kLogError;
using fplutil::kLogImportant;
using fplutil::kLogInfo;
using fplutil::kLogVerbose;
using fplutil::kLogWarning;

static void LogUsage(fplutil::Logger* log) {
  static const char kOptionIndent[] = "                           ";
  log->Log(
      kLogImportant,
      "Usage: anim_pipeline [-v|-d|-i] [-o OUTPUT_FILE]\n"
      "                     [-st SCALE_TOLERANCE] [-rt ROTATE_TOLERANCE]\n"
      "                     [-tt TRANSLATE_TOLERANCE]\n"
      "                     [-at DERIVATIVE_TOLERANCE] [--repeat|--norepeat]\n"
      "                     [--stagger] [--start] [-a AXES]\n"
      "                     [-u (unit)|(scale)] [--roots] [--debug_time TIME]\n"
      "                     FBX_FILE\n"
      "\n"
      "Pipeline to convert FBX animations into FlatBuffer animations.\n"
      "Outputs a .motiveanim file with the same base name as FBX_FILE.\n\n"
      "Options:\n"
      "  -v, --verbose output all informative messages\n"
      "  -d, --details output important informative messages\n"
      "  -i, --info    output more than details, less than verbose.\n"
      "  -o, --out OUTPUT_FILE\n"
      "                file to write .motiveanim file to.\n"
      "                Can be an absolute or relative path.\n"
      "                when unspecified, uses base FBX name + .motiveanim.\n"
      "  -st, --scale SCALE_TOLERANCE\n"
      "                max deviation of output scale curves from input\n"
      "                scale curves; unitless\n"
      "  -rt, --rotate ROTATE_TOLERANCE\n"
      "                max deviation of output rotate curves from intput\n"
      "                rotate curves; in degrees\n"
      "  -tt, --translate TRANSLATE_TOLERANCE\n"
      "                max deviation of output translate curves from input\n"
      "                translate curves; in scene's distance unit\n"
      "  -at, --angle DERIVATIVE_TOLERANCE\n"
      "                max deviation of curve derivatives,\n"
      "                considered as an angle in the x/y plane\n"
      "                (e.g. derivative 1 ==> 45 degrees); in degrees.\n"
      "  --repeat, --norepeat\n"
      "                mark the animation as repeating or not repeating.\n"
      "                A repeating animation cycles over and over.\n"
      "                If neither option is specified, the animation\n"
      "                is marked as repeating when it starts and ends\n"
      "                with the same pose and derivatives.\n"
      "  --stagger, --stagger_end_times\n"
      "                allow every channel to end at its authored time,\n"
      "                instead of adding extra spline nodes to plum-up\n"
      "                every channel.\n"
      "                This may cause strage behavior with animations that\n"
      "                repeat, since the shorter channels will start\n"
      "                to repeat before the longer ones.\n"
      "  --start, --preserve_start_time\n"
      "                start the animation at the same time as in the source.\n"
      "                By default, the animation is shifted such that its\n"
      "                start time is zero.\n"
      "  -a, --axes AXES\n"
      "                coordinate system of exported file, in format\n"
      "                    (up-axis)(front-axis)(left-axis) \n"
      "                where,\n"
      "                    'up' = [x|y|z]\n"
      "                    'front' = [+x|-x|+y|-y|+z|-z], is the axis\n"
      "                      pointing out of the front of the mesh.\n"
      "                      For example, the vector pointing out of a\n"
      "                      character's belly button.\n"
      "                    'left' = [+x|-x|+y|-y|+z|-z], is the axis\n"
      "                      pointing out the left of the mesh.\n"
      "                      For example, the vector from the character's\n"
      "                      neck to his left shoulder.\n"
      "                For example, 'z+y+x' is z-axis up, positive y-axis\n"
      "                out of a character's belly button, positive x-axis\n"
      "                out of a character's left side.\n"
      "                If unspecified, use file's coordinate system.\n"
      "  -u, --unit (unit)|(scale)\n"
      "                output animation in target units. You can override the\n"
      "                FBX file's distance unit with this option.\n"
      "                For example, if your game runs in meters,\n"
      "                specify '-u m' to ensure the output .fplmesh file\n"
      "                is in meters, no matter the distance unit of the\n"
      "                FBX file.\n"
      "                (unit) can be one of the following:\n");
  LogOptions(kOptionIndent, fplutil::DistanceUnitNames(), log);
  log->Log(
      kLogImportant,
      "                (scale) is the number of centimeters in your\n"
      "                distance unit. For example, instead of '-u inches',\n"
      "                you could also use '-u 2.54'.\n"
      "                If unspecified, use FBX file's unit.\n"
      "  --roots, --root_bones_only\n"
      "                output only the root bones of each mesh.\n"
      "                Each mesh gets its animation file.\n"
      "                Useful for pulling just the path data from an\n"
      "                animation.\n"
      "  --debug_time TIME\n"
      "                output the local transforms for each bone in\n"
      "                the animation at TIME, in ms, and then exit.\n"
      "                Useful for debugging situations where the\n"
      "                runtime doesn't match source data.\n");
}

static bool ParseAnimPipelineArgs(int argc, char** argv, fplutil::Logger& log,
                                  motive::AnimPipelineArgs* args) {
  bool valid_args = true;

  // Last parameter is used as file name.
  if (argc > 1) {
    args->fbx_file = string(argv[argc - 1]);
    args->output_file = fplutil::RemoveExtensionFromName(args->fbx_file) + "." +
                        motive::RigAnimFbExtension();
  }

  // Ensure file name is valid.
  const bool valid_fbx_file =
      args->fbx_file.length() > 0 && args->fbx_file[0] != '-';
  if (!valid_fbx_file) {
    valid_args = false;
  }

  // Parse switches.
  for (int i = 1; i < argc - 1; ++i) {
    const string arg = argv[i];

    if (arg == "-v" || arg == "--verbose") {
      args->log_level = kLogVerbose;

    } else if (arg == "-d" || arg == "--details") {
      args->log_level = kLogImportant;

    } else if (arg == "-i" || arg == "--info") {
      args->log_level = kLogInfo;

    } else if (arg == "-o" || arg == "--out") {
      if (i + 1 < argc - 1) {
        args->output_file = string(argv[i + 1]);
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "-st" || arg == "--scale") {
      if (i + 1 < argc - 1) {
        args->tolerances.scale = static_cast<float>(atof(argv[i + 1]));
        if (args->tolerances.scale <= 0.0f) {
          log.Log(kLogError, "scale_tolerance must be > 0.");
          valid_args = false;
        }
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "-rt" || arg == "--rotate") {
      if (i + 1 < argc - 1) {
        const float degrees = static_cast<float>(atof(argv[i + 1]));
        if (degrees <= 0.0f || degrees > 180.0f) {
          log.Log(kLogError, "rotate_tolerance must be >0 and <=180.");
          valid_args = false;
        } else {
          args->tolerances.rotate =
              motive::Angle::FromDegrees(degrees).ToRadians();
          i++;
        }
      } else {
        valid_args = false;
      }

    } else if (arg == "-tt" || arg == "--translate") {
      if (i + 1 < argc - 1) {
        args->tolerances.translate = static_cast<float>(atof(argv[i + 1]));
        if (args->tolerances.translate <= 0.0f) {
          log.Log(kLogError, "translate_tolerance must be > 0.");
          valid_args = false;
        }
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "-at" || arg == "--angle") {
      if (i + 1 < argc - 1) {
        const float degrees = static_cast<float>(atof(argv[i + 1]));
        if (degrees <= 0.0f || degrees > 90.0f) {
          log.Log(kLogError, "derivative_tolerance must be >0 and <=90.");
          valid_args = false;
        } else {
          args->tolerances.derivative_angle =
              motive::Angle::FromDegrees(degrees).ToRadians();
        }
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "--repeat" || arg == "--norepeat") {
      const motive::RepeatPreference repeat_preference =
          arg == "--repeat" ? motive::kAlwaysRepeat : motive::kNeverRepeat;
      if (args->repeat_preference != motive::kRepeatIfRepeatable &&
          args->repeat_preference != repeat_preference) {
        log.Log(kLogError,
                "Only one of --repeat and --norepeat can be specified.\n");
        valid_args = false;
      } else {
        args->repeat_preference = repeat_preference;
      }

    } else if (arg == "--stagger" || arg == "--stagger_end_times") {
      args->stagger_end_times = true;

    } else if (arg == "--start" || arg == "--preserve_start_time") {
      args->preserve_start_time = true;

    } else if (arg == "-a" || arg == "--axes") {
      if (i + 1 < argc - 1) {
        args->axis_system = fplutil::AxisSystemFromName(argv[i + 1]);
        valid_args = args->axis_system >= 0;
        if (!valid_args) {
          log.Log(kLogError, "Unknown coordinate system: %s\n\n", argv[i + 1]);
        }
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "-u" || arg == "--unit") {
      if (i + 1 < argc - 1) {
        args->distance_unit_scale = fplutil::DistanceUnitFromName(argv[i + 1]);
        valid_args = args->distance_unit_scale > 0.0f;
        if (!valid_args) {
          log.Log(kLogError, "Unknown distance unit: %s\n\n", argv[i + 1]);
        }
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "--roots" || arg == "--root_bones_only") {
      args->root_bones_only = true;

    } else if (arg == "--debug_time") {
      if (i + 1 < argc - 1) {
        args->debug_time = atoi(argv[i + 1]);
        args->log_level = kLogInfo;
        if (args->debug_time < 0) {
          log.Log(kLogError, "debug time must be >0.");
          valid_args = false;
        }
        i++;
      } else {
        valid_args = false;
      }

    } else {
      log.Log(kLogError, "Unknown parameter: %s\n", arg.c_str());
      valid_args = false;
    }
  }

  // Print usage.
  if (!valid_args) {
    LogUsage(&log);
  }
  return valid_args;
}

int main(int argc, char** argv) {
  fplutil::Logger log;

  motive::AnimPipelineArgs args;
  if (!ParseAnimPipelineArgs(argc, argv, log, &args)) return 1;

  return motive::RunAnimPipeline(args, log);
}
<commit_msg>Switch string to std::string.  Matches struct definition in anim_pipeline.h.<commit_after>// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "anim_pipeline.h"

#include "anim_generated.h"
#include "fplutil/file_utils.h"
#include "motive/math/angle.h"

using fplutil::kLogError;
using fplutil::kLogImportant;
using fplutil::kLogInfo;
using fplutil::kLogVerbose;
using fplutil::kLogWarning;

static void LogUsage(fplutil::Logger* log) {
  static const char kOptionIndent[] = "                           ";
  log->Log(
      kLogImportant,
      "Usage: anim_pipeline [-v|-d|-i] [-o OUTPUT_FILE]\n"
      "                     [-st SCALE_TOLERANCE] [-rt ROTATE_TOLERANCE]\n"
      "                     [-tt TRANSLATE_TOLERANCE]\n"
      "                     [-at DERIVATIVE_TOLERANCE] [--repeat|--norepeat]\n"
      "                     [--stagger] [--start] [-a AXES]\n"
      "                     [-u (unit)|(scale)] [--roots] [--debug_time TIME]\n"
      "                     FBX_FILE\n"
      "\n"
      "Pipeline to convert FBX animations into FlatBuffer animations.\n"
      "Outputs a .motiveanim file with the same base name as FBX_FILE.\n\n"
      "Options:\n"
      "  -v, --verbose output all informative messages\n"
      "  -d, --details output important informative messages\n"
      "  -i, --info    output more than details, less than verbose.\n"
      "  -o, --out OUTPUT_FILE\n"
      "                file to write .motiveanim file to.\n"
      "                Can be an absolute or relative path.\n"
      "                when unspecified, uses base FBX name + .motiveanim.\n"
      "  -st, --scale SCALE_TOLERANCE\n"
      "                max deviation of output scale curves from input\n"
      "                scale curves; unitless\n"
      "  -rt, --rotate ROTATE_TOLERANCE\n"
      "                max deviation of output rotate curves from intput\n"
      "                rotate curves; in degrees\n"
      "  -tt, --translate TRANSLATE_TOLERANCE\n"
      "                max deviation of output translate curves from input\n"
      "                translate curves; in scene's distance unit\n"
      "  -at, --angle DERIVATIVE_TOLERANCE\n"
      "                max deviation of curve derivatives,\n"
      "                considered as an angle in the x/y plane\n"
      "                (e.g. derivative 1 ==> 45 degrees); in degrees.\n"
      "  --repeat, --norepeat\n"
      "                mark the animation as repeating or not repeating.\n"
      "                A repeating animation cycles over and over.\n"
      "                If neither option is specified, the animation\n"
      "                is marked as repeating when it starts and ends\n"
      "                with the same pose and derivatives.\n"
      "  --stagger, --stagger_end_times\n"
      "                allow every channel to end at its authored time,\n"
      "                instead of adding extra spline nodes to plum-up\n"
      "                every channel.\n"
      "                This may cause strage behavior with animations that\n"
      "                repeat, since the shorter channels will start\n"
      "                to repeat before the longer ones.\n"
      "  --start, --preserve_start_time\n"
      "                start the animation at the same time as in the source.\n"
      "                By default, the animation is shifted such that its\n"
      "                start time is zero.\n"
      "  -a, --axes AXES\n"
      "                coordinate system of exported file, in format\n"
      "                    (up-axis)(front-axis)(left-axis) \n"
      "                where,\n"
      "                    'up' = [x|y|z]\n"
      "                    'front' = [+x|-x|+y|-y|+z|-z], is the axis\n"
      "                      pointing out of the front of the mesh.\n"
      "                      For example, the vector pointing out of a\n"
      "                      character's belly button.\n"
      "                    'left' = [+x|-x|+y|-y|+z|-z], is the axis\n"
      "                      pointing out the left of the mesh.\n"
      "                      For example, the vector from the character's\n"
      "                      neck to his left shoulder.\n"
      "                For example, 'z+y+x' is z-axis up, positive y-axis\n"
      "                out of a character's belly button, positive x-axis\n"
      "                out of a character's left side.\n"
      "                If unspecified, use file's coordinate system.\n"
      "  -u, --unit (unit)|(scale)\n"
      "                output animation in target units. You can override the\n"
      "                FBX file's distance unit with this option.\n"
      "                For example, if your game runs in meters,\n"
      "                specify '-u m' to ensure the output .fplmesh file\n"
      "                is in meters, no matter the distance unit of the\n"
      "                FBX file.\n"
      "                (unit) can be one of the following:\n");
  LogOptions(kOptionIndent, fplutil::DistanceUnitNames(), log);
  log->Log(
      kLogImportant,
      "                (scale) is the number of centimeters in your\n"
      "                distance unit. For example, instead of '-u inches',\n"
      "                you could also use '-u 2.54'.\n"
      "                If unspecified, use FBX file's unit.\n"
      "  --roots, --root_bones_only\n"
      "                output only the root bones of each mesh.\n"
      "                Each mesh gets its animation file.\n"
      "                Useful for pulling just the path data from an\n"
      "                animation.\n"
      "  --debug_time TIME\n"
      "                output the local transforms for each bone in\n"
      "                the animation at TIME, in ms, and then exit.\n"
      "                Useful for debugging situations where the\n"
      "                runtime doesn't match source data.\n");
}

static bool ParseAnimPipelineArgs(int argc, char** argv, fplutil::Logger& log,
                                  motive::AnimPipelineArgs* args) {
  bool valid_args = true;

  // Last parameter is used as file name.
  if (argc > 1) {
    args->fbx_file = std::string(argv[argc - 1]);
    args->output_file = fplutil::RemoveExtensionFromName(args->fbx_file) + "." +
                        motive::RigAnimFbExtension();
  }

  // Ensure file name is valid.
  const bool valid_fbx_file =
      args->fbx_file.length() > 0 && args->fbx_file[0] != '-';
  if (!valid_fbx_file) {
    valid_args = false;
  }

  // Parse switches.
  for (int i = 1; i < argc - 1; ++i) {
    const std::string arg = argv[i];

    if (arg == "-v" || arg == "--verbose") {
      args->log_level = kLogVerbose;

    } else if (arg == "-d" || arg == "--details") {
      args->log_level = kLogImportant;

    } else if (arg == "-i" || arg == "--info") {
      args->log_level = kLogInfo;

    } else if (arg == "-o" || arg == "--out") {
      if (i + 1 < argc - 1) {
        args->output_file = std::string(argv[i + 1]);
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "-st" || arg == "--scale") {
      if (i + 1 < argc - 1) {
        args->tolerances.scale = static_cast<float>(atof(argv[i + 1]));
        if (args->tolerances.scale <= 0.0f) {
          log.Log(kLogError, "scale_tolerance must be > 0.");
          valid_args = false;
        }
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "-rt" || arg == "--rotate") {
      if (i + 1 < argc - 1) {
        const float degrees = static_cast<float>(atof(argv[i + 1]));
        if (degrees <= 0.0f || degrees > 180.0f) {
          log.Log(kLogError, "rotate_tolerance must be >0 and <=180.");
          valid_args = false;
        } else {
          args->tolerances.rotate =
              motive::Angle::FromDegrees(degrees).ToRadians();
          i++;
        }
      } else {
        valid_args = false;
      }

    } else if (arg == "-tt" || arg == "--translate") {
      if (i + 1 < argc - 1) {
        args->tolerances.translate = static_cast<float>(atof(argv[i + 1]));
        if (args->tolerances.translate <= 0.0f) {
          log.Log(kLogError, "translate_tolerance must be > 0.");
          valid_args = false;
        }
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "-at" || arg == "--angle") {
      if (i + 1 < argc - 1) {
        const float degrees = static_cast<float>(atof(argv[i + 1]));
        if (degrees <= 0.0f || degrees > 90.0f) {
          log.Log(kLogError, "derivative_tolerance must be >0 and <=90.");
          valid_args = false;
        } else {
          args->tolerances.derivative_angle =
              motive::Angle::FromDegrees(degrees).ToRadians();
        }
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "--repeat" || arg == "--norepeat") {
      const motive::RepeatPreference repeat_preference =
          arg == "--repeat" ? motive::kAlwaysRepeat : motive::kNeverRepeat;
      if (args->repeat_preference != motive::kRepeatIfRepeatable &&
          args->repeat_preference != repeat_preference) {
        log.Log(kLogError,
                "Only one of --repeat and --norepeat can be specified.\n");
        valid_args = false;
      } else {
        args->repeat_preference = repeat_preference;
      }

    } else if (arg == "--stagger" || arg == "--stagger_end_times") {
      args->stagger_end_times = true;

    } else if (arg == "--start" || arg == "--preserve_start_time") {
      args->preserve_start_time = true;

    } else if (arg == "-a" || arg == "--axes") {
      if (i + 1 < argc - 1) {
        args->axis_system = fplutil::AxisSystemFromName(argv[i + 1]);
        valid_args = args->axis_system >= 0;
        if (!valid_args) {
          log.Log(kLogError, "Unknown coordinate system: %s\n\n", argv[i + 1]);
        }
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "-u" || arg == "--unit") {
      if (i + 1 < argc - 1) {
        args->distance_unit_scale = fplutil::DistanceUnitFromName(argv[i + 1]);
        valid_args = args->distance_unit_scale > 0.0f;
        if (!valid_args) {
          log.Log(kLogError, "Unknown distance unit: %s\n\n", argv[i + 1]);
        }
        i++;
      } else {
        valid_args = false;
      }

    } else if (arg == "--roots" || arg == "--root_bones_only") {
      args->root_bones_only = true;

    } else if (arg == "--debug_time") {
      if (i + 1 < argc - 1) {
        args->debug_time = atoi(argv[i + 1]);
        args->log_level = kLogInfo;
        if (args->debug_time < 0) {
          log.Log(kLogError, "debug time must be >0.");
          valid_args = false;
        }
        i++;
      } else {
        valid_args = false;
      }

    } else {
      log.Log(kLogError, "Unknown parameter: %s\n", arg.c_str());
      valid_args = false;
    }
  }

  // Print usage.
  if (!valid_args) {
    LogUsage(&log);
  }
  return valid_args;
}

int main(int argc, char** argv) {
  fplutil::Logger log;

  motive::AnimPipelineArgs args;
  if (!ParseAnimPipelineArgs(argc, argv, log, &args)) return 1;

  return motive::RunAnimPipeline(args, log);
}
<|endoftext|>


<commit_before>#include <json.h>
#include <remote_api.h>
#include <ttrss_api.h>
#include <cstring>
#include <algorithm>

namespace newsbeuter {

ttrss_api::ttrss_api(configcontainer * c) : remote_api(c) {
	single = (cfg->get_configvalue("ttrss-mode") == "single");
	auth_info = utils::strprintf("%s:%s", cfg->get_configvalue("ttrss-login").c_str(), cfg->get_configvalue("ttrss-password").c_str());
	auth_info_ptr = auth_info.c_str();
	sid = "";
}

ttrss_api::~ttrss_api() {
}

bool ttrss_api::authenticate() {
	 if (auth_lock.trylock()) {
		sid = retrieve_sid();
		auth_lock.unlock();
	 } else {
	 	// wait for other thread to finish and return its result:
	 	auth_lock.lock();
	 	auth_lock.unlock();
	 }

	return sid != "";
}

std::string ttrss_api::retrieve_sid() {
	CURL * handle = curl_easy_init();
	char * user = curl_easy_escape(handle, cfg->get_configvalue("ttrss-login").c_str(), 0);
	char * pass = curl_easy_escape(handle, cfg->get_configvalue("ttrss-password").c_str(), 0);

	std::map<std::string, std::string> args;
	args["user"] = single ? "admin" : std::string(user);
	args["password"] = std::string(pass);
	struct json_object * content = run_op("login", args);

	curl_free(user);
	curl_free(pass);

	if (content == NULL)
		return "";

	std::string sid;

	struct json_object * session_id = json_object_object_get(content, "session_id");
	sid = json_object_get_string(session_id);

	json_object_put(content);

	LOG(LOG_DEBUG, "ttrss_api::retrieve_sid: sid = '%s'", sid.c_str());

	return sid;
}

struct json_object * ttrss_api::run_op(const std::string& op,
				       const std::map<std::string, std::string >& args,
				       bool try_login) {
	std::string url = utils::strprintf("%s/api/?op=%s&sid=%s", cfg->get_configvalue("ttrss-url").c_str(),
		op.c_str(), sid.c_str());

	for (std::map<std::string, std::string>::const_iterator it = args.begin(); it != args.end(); it++) {
		url += "&" + it->first + "=" + it->second;
	}
	std::string result = utils::retrieve_url(url, cfg, auth_info_ptr);

	LOG(LOG_DEBUG, "ttrss_api::run_op(%s,...): reply = %s", op.c_str(), result.c_str());

	struct json_object * reply = json_tokener_parse(result.c_str());
	if (is_error(reply)) {
		LOG(LOG_ERROR, "ttrss_api::run_op: reply failed to parse: %s", result.c_str());
		return NULL;
	}

	struct json_object * status = json_object_object_get(reply, "status");
	struct json_object * content = json_object_object_get(reply, "content");
	if (json_object_get_int(status) != 0) {
		struct json_object * error = json_object_object_get(content, "error");
		if ((strcmp(json_object_get_string(error), "NOT_LOGGED_IN") == 0) && try_login) {
			json_object_put(reply);
			if (authenticate())
				return run_op(op, args, false);
			else
				return NULL;
		} else {
			json_object_put(reply);
			return NULL;
		}
	}

	// free the parent object, without freeing content as well:
	json_object_get(content);
	json_object_put(reply);
	return content;
}

std::vector<tagged_feedurl> ttrss_api::get_subscribed_urls() {

	std::string cat_url = utils::strprintf("%s/api/?op=getCategories&sid=%s", cfg->get_configvalue("ttrss-url").c_str(), sid.c_str());
	std::string result = utils::retrieve_url(cat_url, cfg, auth_info_ptr);

	LOG(LOG_DEBUG, "ttrss_api::get_subscribed_urls: reply = %s", result.c_str());

	std::vector<tagged_feedurl> feeds;

	struct json_object * content = run_op("getCategories", std::map<std::string, std::string>());
	if (!content)
		return feeds;

	if (json_object_get_type(content) != json_type_array)
		return feeds;

	struct array_list * categories = json_object_get_array(content);

	int catsize = array_list_length(categories);

	// first fetch feeds within no category
	fetch_feeds_per_category(NULL, feeds);

	// then fetch the feeds of all categories
	for (int i=0;i<catsize;i++) {
		struct json_object * cat = (struct json_object *)array_list_get_idx(categories, i);
		fetch_feeds_per_category(cat, feeds);
	}

	json_object_put(content);

	return feeds;
}

void ttrss_api::configure_handle(CURL * /*handle*/) {
	// nothing required
}

bool ttrss_api::mark_all_read(const std::string& feed_url) {

	std::map<std::string, std::string> args;
	args["feed_id"] = url_to_id(feed_url);
	struct json_object * content = run_op("catchupFeed", args);

	if(!content)
		return false;

	json_object_put(content);
	return true;
}

bool ttrss_api::mark_article_read(const std::string& guid, bool read) {
	return update_article(guid, 2, read ? 0 : 1);
}

bool ttrss_api::update_article_flags(const std::string& oldflags, const std::string& newflags, const std::string& guid) {
	std::string star_flag = cfg->get_configvalue("ttrss-flag-star");
	std::string publish_flag = cfg->get_configvalue("ttrss-flag-publish");
	bool success = true;

	if (star_flag.length() > 0) {
		if (strchr(oldflags.c_str(), star_flag[0])==NULL && strchr(newflags.c_str(), star_flag[0])!=NULL) {
			success = star_article(guid, true);
		} else if (strchr(oldflags.c_str(), star_flag[0])!=NULL && strchr(newflags.c_str(), star_flag[0])==NULL) {
			success = star_article(guid, false);
		}
	}

	if (publish_flag.length() > 0) {
		if (strchr(oldflags.c_str(), publish_flag[0])==NULL && strchr(newflags.c_str(), publish_flag[0])!=NULL) {
			success = publish_article(guid, true);
		} else if (strchr(oldflags.c_str(), publish_flag[0])!=NULL && strchr(newflags.c_str(), publish_flag[0])==NULL) {
			success = publish_article(guid, false);
		}
	}

	return success;
}

static bool sort_by_pubdate(const rsspp::item& a, const rsspp::item& b) {
	return a.pubDate_ts > b.pubDate_ts;
}

rsspp::feed ttrss_api::fetch_feed(const std::string& id) {
	rsspp::feed f;

	f.rss_version = rsspp::TTRSS_JSON;

	std::map<std::string, std::string> args;
	args["feed_id"] = id;
	args["show_content"] = "1";
	struct json_object * content = run_op("getHeadlines", args);

	if (!content)
		return f;

	if (json_object_get_type(content) != json_type_array) {
		LOG(LOG_ERROR, "ttrss_api::fetch_feed: content is not an array");
		return f;
	}

	struct array_list * items = json_object_get_array(content);
	int items_size = array_list_length(items);
	LOG(LOG_DEBUG, "ttrss_api::fetch_feed: %d items", items_size);

	for (int i=0;i<items_size;i++) {
		struct json_object * item_obj = (struct json_object *)array_list_get_idx(items, i);
		int id = json_object_get_int(json_object_object_get(item_obj, "id"));
		const char * title = json_object_get_string(json_object_object_get(item_obj, "title"));
		const char * link = json_object_get_string(json_object_object_get(item_obj, "link"));
		const char * content = json_object_get_string(json_object_object_get(item_obj, "content"));
		time_t updated = (time_t)json_object_get_int(json_object_object_get(item_obj, "updated"));
		boolean unread = json_object_get_boolean(json_object_object_get(item_obj, "unread"));

		rsspp::item item;

		if (title)
			item.title = title;

		if (link)
			item.link = link;

		if (content)
			item.content_encoded = content;

		item.guid = utils::strprintf("%d", id);

		if (unread) {
			item.labels.push_back("ttrss:unread");
		} else {
			item.labels.push_back("ttrss:read");
		}

		char rfc822_date[128];
		strftime(rfc822_date, sizeof(rfc822_date), "%a, %d %b %Y %H:%M:%S %z", gmtime(&updated));
		item.pubDate = rfc822_date;
		item.pubDate_ts = updated;

		f.items.push_back(item);
	}

	std::sort(f.items.begin(), f.items.end(), sort_by_pubdate);

	json_object_put(content);
	return f;
}

void ttrss_api::fetch_feeds_per_category(struct json_object * cat, std::vector<tagged_feedurl>& feeds) {
	const char * cat_name = NULL;
	struct json_object * cat_title_obj = NULL;
	int cat_id;

	if (cat) {
		struct json_object * cat_id_obj = json_object_object_get(cat, "id");
		cat_id = json_object_get_int(cat_id_obj);

		cat_title_obj = json_object_object_get(cat, "title");
		cat_name = json_object_get_string(cat_title_obj);
		LOG(LOG_DEBUG, "ttrss_api::fetch_feeds_per_category: id = %d title = %s", cat_id, cat_name);
	}

	std::map<std::string, std::string> args;
	if (cat)
		args["cat_id"] = utils::to_s(cat_id);
	struct json_object * feed_list_obj = run_op("getFeeds", args);

	if (!feed_list_obj)
		return;

	struct array_list * feed_list = json_object_get_array(feed_list_obj);

	int feed_list_size = array_list_length(feed_list);

	for (int j=0;j<feed_list_size;j++) {
		struct json_object * feed = (struct json_object *)array_list_get_idx(feed_list, j);

		int feed_id = json_object_get_int(json_object_object_get(feed, "id"));
		const char * feed_title = json_object_get_string(json_object_object_get(feed, "title"));
		const char * feed_url = json_object_get_string(json_object_object_get(feed, "feed_url"));

		std::vector<std::string> tags;
		tags.push_back(std::string("~") + feed_title);
		if (cat_name) {
			tags.push_back(cat_name);
		}
		feeds.push_back(tagged_feedurl(utils::strprintf("%s#%d", feed_url, feed_id), tags));

		// TODO: cache feed_id -> feed_url (or feed_url -> feed_id ?)
	}

	json_object_put(feed_list_obj);

}

bool ttrss_api::star_article(const std::string& guid, bool star) {
	return update_article(guid, 0, star ? 1 : 0);
}

bool ttrss_api::publish_article(const std::string& guid, bool publish) {
	return update_article(guid, 1, publish ? 1 : 0);
}

bool ttrss_api::update_article(const std::string& guid, int field, int mode) {

	std::map<std::string, std::string> args;
	args["article_ids"] = guid;
	args["field"] = utils::to_s(field);
	args["mode"] = utils::to_s(mode);
	struct json_object * content = run_op("updateArticle", args);

	if (!content)
	    return false;

	json_object_put(content);
	return true;
}

std::string ttrss_api::url_to_id(const std::string& url) {
	const char * uri = url.c_str();
	const char * pound = strrchr(uri, '#');
	if (!pound)
		return "";
	return std::string(pound+1);
}

}
<commit_msg>tt-rss: Some more error checking<commit_after>#include <json.h>
#include <remote_api.h>
#include <ttrss_api.h>
#include <cstring>
#include <algorithm>

namespace newsbeuter {

ttrss_api::ttrss_api(configcontainer * c) : remote_api(c) {
	single = (cfg->get_configvalue("ttrss-mode") == "single");
	auth_info = utils::strprintf("%s:%s", cfg->get_configvalue("ttrss-login").c_str(), cfg->get_configvalue("ttrss-password").c_str());
	auth_info_ptr = auth_info.c_str();
	sid = "";
}

ttrss_api::~ttrss_api() {
}

bool ttrss_api::authenticate() {
	 if (auth_lock.trylock()) {
		sid = retrieve_sid();
		auth_lock.unlock();
	 } else {
	 	// wait for other thread to finish and return its result:
	 	auth_lock.lock();
	 	auth_lock.unlock();
	 }

	return sid != "";
}

std::string ttrss_api::retrieve_sid() {
	CURL * handle = curl_easy_init();
	char * user = curl_easy_escape(handle, cfg->get_configvalue("ttrss-login").c_str(), 0);
	char * pass = curl_easy_escape(handle, cfg->get_configvalue("ttrss-password").c_str(), 0);

	std::map<std::string, std::string> args;
	args["user"] = single ? "admin" : std::string(user);
	args["password"] = std::string(pass);
	struct json_object * content = run_op("login", args);

	curl_free(user);
	curl_free(pass);

	if (content == NULL)
		return "";

	std::string sid;

	struct json_object * session_id = json_object_object_get(content, "session_id");
	sid = json_object_get_string(session_id);

	json_object_put(content);

	LOG(LOG_DEBUG, "ttrss_api::retrieve_sid: sid = '%s'", sid.c_str());

	return sid;
}

struct json_object * ttrss_api::run_op(const std::string& op,
				       const std::map<std::string, std::string >& args,
				       bool try_login) {
	std::string url = utils::strprintf("%s/api/?op=%s&sid=%s", cfg->get_configvalue("ttrss-url").c_str(),
		op.c_str(), sid.c_str());

	for (std::map<std::string, std::string>::const_iterator it = args.begin(); it != args.end(); it++) {
		url += "&" + it->first + "=" + it->second;
	}
	std::string result = utils::retrieve_url(url, cfg, auth_info_ptr);

	LOG(LOG_DEBUG, "ttrss_api::run_op(%s,...): reply = %s", op.c_str(), result.c_str());

	struct json_object * reply = json_tokener_parse(result.c_str());
	if (is_error(reply)) {
		LOG(LOG_ERROR, "ttrss_api::run_op: reply failed to parse: %s", result.c_str());
		return NULL;
	}

	struct json_object * status = json_object_object_get(reply, "status");
	if (is_error(status)) {
		LOG(LOG_ERROR, "ttrss_api::run_op: no status code");
		return NULL;
	}

	struct json_object * content = json_object_object_get(reply, "content");
	if (is_error(content)) {
		LOG(LOG_ERROR, "ttrss_api::run_op: no content part in answer from server");
		return NULL;
	}

	if (json_object_get_int(status) != 0) {
		struct json_object * error = json_object_object_get(content, "error");
		if ((strcmp(json_object_get_string(error), "NOT_LOGGED_IN") == 0) && try_login) {
			json_object_put(reply);
			if (authenticate())
				return run_op(op, args, false);
			else
				return NULL;
		} else {
			json_object_put(reply);
			return NULL;
		}
	}

	// free the parent object, without freeing content as well:
	json_object_get(content);
	json_object_put(reply);
	return content;
}

std::vector<tagged_feedurl> ttrss_api::get_subscribed_urls() {

	std::string cat_url = utils::strprintf("%s/api/?op=getCategories&sid=%s", cfg->get_configvalue("ttrss-url").c_str(), sid.c_str());
	std::string result = utils::retrieve_url(cat_url, cfg, auth_info_ptr);

	LOG(LOG_DEBUG, "ttrss_api::get_subscribed_urls: reply = %s", result.c_str());

	std::vector<tagged_feedurl> feeds;

	struct json_object * content = run_op("getCategories", std::map<std::string, std::string>());
	if (!content)
		return feeds;

	if (json_object_get_type(content) != json_type_array)
		return feeds;

	struct array_list * categories = json_object_get_array(content);

	int catsize = array_list_length(categories);

	// first fetch feeds within no category
	fetch_feeds_per_category(NULL, feeds);

	// then fetch the feeds of all categories
	for (int i=0;i<catsize;i++) {
		struct json_object * cat = (struct json_object *)array_list_get_idx(categories, i);
		fetch_feeds_per_category(cat, feeds);
	}

	json_object_put(content);

	return feeds;
}

void ttrss_api::configure_handle(CURL * /*handle*/) {
	// nothing required
}

bool ttrss_api::mark_all_read(const std::string& feed_url) {

	std::map<std::string, std::string> args;
	args["feed_id"] = url_to_id(feed_url);
	struct json_object * content = run_op("catchupFeed", args);

	if(!content)
		return false;

	json_object_put(content);
	return true;
}

bool ttrss_api::mark_article_read(const std::string& guid, bool read) {
	return update_article(guid, 2, read ? 0 : 1);
}

bool ttrss_api::update_article_flags(const std::string& oldflags, const std::string& newflags, const std::string& guid) {
	std::string star_flag = cfg->get_configvalue("ttrss-flag-star");
	std::string publish_flag = cfg->get_configvalue("ttrss-flag-publish");
	bool success = true;

	if (star_flag.length() > 0) {
		if (strchr(oldflags.c_str(), star_flag[0])==NULL && strchr(newflags.c_str(), star_flag[0])!=NULL) {
			success = star_article(guid, true);
		} else if (strchr(oldflags.c_str(), star_flag[0])!=NULL && strchr(newflags.c_str(), star_flag[0])==NULL) {
			success = star_article(guid, false);
		}
	}

	if (publish_flag.length() > 0) {
		if (strchr(oldflags.c_str(), publish_flag[0])==NULL && strchr(newflags.c_str(), publish_flag[0])!=NULL) {
			success = publish_article(guid, true);
		} else if (strchr(oldflags.c_str(), publish_flag[0])!=NULL && strchr(newflags.c_str(), publish_flag[0])==NULL) {
			success = publish_article(guid, false);
		}
	}

	return success;
}

static bool sort_by_pubdate(const rsspp::item& a, const rsspp::item& b) {
	return a.pubDate_ts > b.pubDate_ts;
}

rsspp::feed ttrss_api::fetch_feed(const std::string& id) {
	rsspp::feed f;

	f.rss_version = rsspp::TTRSS_JSON;

	std::map<std::string, std::string> args;
	args["feed_id"] = id;
	args["show_content"] = "1";
	struct json_object * content = run_op("getHeadlines", args);

	if (!content)
		return f;

	if (json_object_get_type(content) != json_type_array) {
		LOG(LOG_ERROR, "ttrss_api::fetch_feed: content is not an array");
		return f;
	}

	struct array_list * items = json_object_get_array(content);
	int items_size = array_list_length(items);
	LOG(LOG_DEBUG, "ttrss_api::fetch_feed: %d items", items_size);

	for (int i=0;i<items_size;i++) {
		struct json_object * item_obj = (struct json_object *)array_list_get_idx(items, i);
		int id = json_object_get_int(json_object_object_get(item_obj, "id"));
		const char * title = json_object_get_string(json_object_object_get(item_obj, "title"));
		const char * link = json_object_get_string(json_object_object_get(item_obj, "link"));
		const char * content = json_object_get_string(json_object_object_get(item_obj, "content"));
		time_t updated = (time_t)json_object_get_int(json_object_object_get(item_obj, "updated"));
		boolean unread = json_object_get_boolean(json_object_object_get(item_obj, "unread"));

		rsspp::item item;

		if (title)
			item.title = title;

		if (link)
			item.link = link;

		if (content)
			item.content_encoded = content;

		item.guid = utils::strprintf("%d", id);

		if (unread) {
			item.labels.push_back("ttrss:unread");
		} else {
			item.labels.push_back("ttrss:read");
		}

		char rfc822_date[128];
		strftime(rfc822_date, sizeof(rfc822_date), "%a, %d %b %Y %H:%M:%S %z", gmtime(&updated));
		item.pubDate = rfc822_date;
		item.pubDate_ts = updated;

		f.items.push_back(item);
	}

	std::sort(f.items.begin(), f.items.end(), sort_by_pubdate);

	json_object_put(content);
	return f;
}

void ttrss_api::fetch_feeds_per_category(struct json_object * cat, std::vector<tagged_feedurl>& feeds) {
	const char * cat_name = NULL;
	struct json_object * cat_title_obj = NULL;
	int cat_id;

	if (cat) {
		struct json_object * cat_id_obj = json_object_object_get(cat, "id");
		cat_id = json_object_get_int(cat_id_obj);

		cat_title_obj = json_object_object_get(cat, "title");
		cat_name = json_object_get_string(cat_title_obj);
		LOG(LOG_DEBUG, "ttrss_api::fetch_feeds_per_category: id = %d title = %s", cat_id, cat_name);
	}

	std::map<std::string, std::string> args;
	if (cat)
		args["cat_id"] = utils::to_s(cat_id);
	struct json_object * feed_list_obj = run_op("getFeeds", args);

	if (!feed_list_obj)
		return;

	struct array_list * feed_list = json_object_get_array(feed_list_obj);

	int feed_list_size = array_list_length(feed_list);

	for (int j=0;j<feed_list_size;j++) {
		struct json_object * feed = (struct json_object *)array_list_get_idx(feed_list, j);

		int feed_id = json_object_get_int(json_object_object_get(feed, "id"));
		const char * feed_title = json_object_get_string(json_object_object_get(feed, "title"));
		const char * feed_url = json_object_get_string(json_object_object_get(feed, "feed_url"));

		std::vector<std::string> tags;
		tags.push_back(std::string("~") + feed_title);
		if (cat_name) {
			tags.push_back(cat_name);
		}
		feeds.push_back(tagged_feedurl(utils::strprintf("%s#%d", feed_url, feed_id), tags));

		// TODO: cache feed_id -> feed_url (or feed_url -> feed_id ?)
	}

	json_object_put(feed_list_obj);

}

bool ttrss_api::star_article(const std::string& guid, bool star) {
	return update_article(guid, 0, star ? 1 : 0);
}

bool ttrss_api::publish_article(const std::string& guid, bool publish) {
	return update_article(guid, 1, publish ? 1 : 0);
}

bool ttrss_api::update_article(const std::string& guid, int field, int mode) {

	std::map<std::string, std::string> args;
	args["article_ids"] = guid;
	args["field"] = utils::to_s(field);
	args["mode"] = utils::to_s(mode);
	struct json_object * content = run_op("updateArticle", args);

	if (!content)
	    return false;

	json_object_put(content);
	return true;
}

std::string ttrss_api::url_to_id(const std::string& url) {
	const char * uri = url.c_str();
	const char * pound = strrchr(uri, '#');
	if (!pound)
		return "";
	return std::string(pound+1);
}

}
<|endoftext|>


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

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

#ifndef _SVX_SVDOIMP_HXX
#include <svdoimp.hxx>
#endif

#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif

#ifndef _SVX_XLNSTIT_HXX
#include <xlnstit.hxx>
#endif

#ifndef _SVX_XLNEDIT_HXX
#include "xlnedit.hxx"
#endif

#ifndef _SVX_XLNWTIT_HXX
#include <xlnwtit.hxx>
#endif

#ifndef _SVX_XLINEIT0_HXX
#include <xlineit0.hxx>
#endif

#ifndef _SVX_XLNSTWIT_HXX
#include <xlnstwit.hxx>
#endif

#ifndef _SVX_XLNEDWIT_HXX
#include <xlnedwit.hxx>
#endif

#ifndef _SVX_XLNSTCIT_HXX
#include <xlnstcit.hxx>
#endif

#ifndef _SVX_XLNEDCIT_HXX
#include <xlnedcit.hxx>
#endif

#ifndef _SVX_XLINJOIT_HXX
#include <xlinjoit.hxx>
#endif

#ifndef _SVX_XLNDSIT_HXX
#include <xlndsit.hxx>
#endif

#ifndef _BGFX_POLYGON_B2DPOLYGON_HXX
#include <basegfx/polygon/b2dpolygon.hxx>
#endif

#ifndef _BGFX_POINT_B2DPOINT_HXX
#include <basegfx/point/b2dpoint.hxx>
#endif

#ifndef _BGFX_VECTOR_B2DVECTOR_HXX
#include <basegfx/vector/b2dvector.hxx>
#endif

#ifndef _BGFX_RANGE_B2DRANGE_HXX
#include <basegfx/range/b2drange.hxx>
#endif

#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX
#include <basegfx/polygon/b2dpolygontools.hxx>
#endif

#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif

#ifndef _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#endif

#ifndef _BGFX_POLYGON_B2DLINEGEOMETRY_HXX
#include <basegfx/polygon/b2dlinegeometry.hxx>
#endif

///////////////////////////////////////////////////////////////////////////////

ImpLineStyleParameterPack::ImpLineStyleParameterPack(
    const SfxItemSet& rSet,
    bool _bForceHair)
:   mbForceNoArrowsLeft(false),
    mbForceNoArrowsRight(false),
    mbForceHair(_bForceHair)
{
    maStartPolyPolygon = ((const XLineStartItem&)(rSet.Get(XATTR_LINESTART))).GetLineStartValue();

    if(maStartPolyPolygon.count())
    {
        if(maStartPolyPolygon.areControlPointsUsed())
        {
            maStartPolyPolygon = basegfx::tools::adaptiveSubdivideByAngle(maStartPolyPolygon);
        }

        if(basegfx::ORIENTATION_NEGATIVE == basegfx::tools::getOrientation(maStartPolyPolygon.getB2DPolygon(0L)))
        {
            maStartPolyPolygon.flip();
        }
    }

    maEndPolyPolygon = ((const XLineEndItem&)(rSet.Get(XATTR_LINEEND))).GetLineEndValue();

    if(maEndPolyPolygon.count())
    {
        if(maEndPolyPolygon.areControlPointsUsed())
        {
            maEndPolyPolygon = basegfx::tools::adaptiveSubdivideByAngle(maEndPolyPolygon);
        }

        if(basegfx::ORIENTATION_NEGATIVE == basegfx::tools::getOrientation(maEndPolyPolygon.getB2DPolygon(0L)))
        {
            maEndPolyPolygon.flip();
        }
    }

    mnLineWidth = ((const XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue();
    mbLineStyleSolid = (XLINE_SOLID == (XLineStyle)((const XLineStyleItem&)rSet.Get(XATTR_LINESTYLE)).GetValue());

    mnStartWidth = ((const XLineStartWidthItem&)(rSet.Get(XATTR_LINESTARTWIDTH))).GetValue();
    if(mnStartWidth < 0)
        mnStartWidth = -mnLineWidth * mnStartWidth / 100L;

    mnEndWidth = ((const XLineEndWidthItem&)(rSet.Get(XATTR_LINEENDWIDTH))).GetValue();
    if(mnEndWidth < 0)
        mnEndWidth = -mnLineWidth * mnEndWidth / 100L;

    mbStartCentered = ((const XLineStartCenterItem&)(rSet.Get(XATTR_LINESTARTCENTER))).GetValue();
    mbEndCentered = ((const XLineEndCenterItem&)(rSet.Get(XATTR_LINEENDCENTER))).GetValue();

    mfDegreeStepWidth = 10.0;
    meLineJoint = ((const XLineJointItem&)(rSet.Get(XATTR_LINEJOINT))).GetValue();

    XDash aDash = ((const XLineDashItem&)(rSet.Get(XATTR_LINEDASH))).GetDashValue();

    // fill local dash info
    mfFullDotDashLen = aDash.CreateDotDashArray(maDotDashArray, (double)GetDisplayLineWidth());
}

ImpLineStyleParameterPack::~ImpLineStyleParameterPack()
{
}

bool ImpLineStyleParameterPack::IsStartActive() const
{
    if(!mbForceNoArrowsLeft && maStartPolyPolygon.count() && GetStartWidth())
    {
        return (0L != maStartPolyPolygon.getB2DPolygon(0L).count());
    }

    return false;
}

bool ImpLineStyleParameterPack::IsEndActive() const
{
    if(!mbForceNoArrowsRight && maEndPolyPolygon.count() && GetEndWidth())
    {
        return (0L != maEndPolyPolygon.getB2DPolygon(0L).count());
    }

    return false;
}

void ImpLineGeometryCreator::ImpCreateLineGeometry(const basegfx::B2DPolygon& rSourcePoly)
{
    if(rSourcePoly.count() > 1L)
    {
        basegfx::B2DPolygon aSourceLineGeometry(rSourcePoly);

        if(aSourceLineGeometry.areControlPointsUsed())
        {
            aSourceLineGeometry = basegfx::tools::adaptiveSubdivideByAngle(aSourceLineGeometry);
        }

        sal_uInt32 nCount(aSourceLineGeometry.count());

        if(!aSourceLineGeometry.isClosed())
        {
            nCount--;
            const double fPolyLength(basegfx::tools::getLength(aSourceLineGeometry));
            double fStart(0.0);
            double fEnd(0.0);

            if(mrLineAttr.IsStartActive())
            {
                // create line start polygon and move line end
                basegfx::B2DPolyPolygon aArrowPolyPolygon;
                aArrowPolyPolygon.append(mrLineAttr.GetStartPolyPolygon());

                basegfx::B2DPolyPolygon aArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
                    aSourceLineGeometry,
                    aArrowPolyPolygon,
                    true,
                    (double)mrLineAttr.GetStartWidth(),
                    mrLineAttr.IsStartCentered() ? 0.5 : 0.0,
                    &fStart);

                maAreaPolyPolygon.append(aArrow);
                fStart *= 0.8;
            }

            if(mrLineAttr.IsEndActive())
            {
                // create line end polygon and move line end
                basegfx::B2DPolyPolygon aArrowPolyPolygon;
                aArrowPolyPolygon.append(mrLineAttr.GetEndPolyPolygon());

                basegfx::B2DPolyPolygon aArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
                    aSourceLineGeometry,
                    aArrowPolyPolygon,
                    false,
                    (double)mrLineAttr.GetEndWidth(),
                    mrLineAttr.IsEndCentered() ? 0.5 : 0.0,
                    &fEnd);

                maAreaPolyPolygon.append(aArrow);
                fEnd *= 0.8;
            }

            if(fStart != 0.0 || fEnd != 0.0)
            {
                // build new poly, consume something from old poly
                aSourceLineGeometry = basegfx::tools::getSnippetAbsolute(
                    aSourceLineGeometry, fStart, fPolyLength - fEnd, fPolyLength);
                nCount = aSourceLineGeometry.count() - 1L;
            }
        }

        if(nCount)
        {
            basegfx::B2DPolyPolygon aHairLinePolyPolygon;

            if(mbLineDraft || mrLineAttr.IsLineStyleSolid())
            {
                // no LineStyle
                aHairLinePolyPolygon.append(aSourceLineGeometry);
            }
            else
            {
                // apply LineStyle
                aHairLinePolyPolygon = basegfx::tools::applyLineDashing(aSourceLineGeometry, mrLineAttr.GetDotDash(), mrLineAttr.GetFullDotDashLen());

                // merge LineStyle polygons to bigger parts
                aHairLinePolyPolygon = basegfx::tools::mergeDashedLines(aHairLinePolyPolygon);
            }

            if(!mrLineAttr.GetDisplayLineWidth())
            {
                // LineWidth zero, add directly to linePoly
                maLinePolyPolygon.append(aHairLinePolyPolygon);
            }
            else
            {
                basegfx::tools::B2DLineJoin aB2DLineJoin(basegfx::tools::B2DLINEJOIN_NONE);

                switch(mrLineAttr.GetLineJoint())
                {
                case XLINEJOINT_NONE    : aB2DLineJoin = basegfx::tools::B2DLINEJOIN_NONE;  break;
                case XLINEJOINT_MIDDLE  : aB2DLineJoin = basegfx::tools::B2DLINEJOIN_MIDDLE;    break;
                case XLINEJOINT_BEVEL   : aB2DLineJoin = basegfx::tools::B2DLINEJOIN_BEVEL; break;
                case XLINEJOINT_MITER   : aB2DLineJoin = basegfx::tools::B2DLINEJOIN_MITER; break;
                case XLINEJOINT_ROUND   : aB2DLineJoin = basegfx::tools::B2DLINEJOIN_ROUND; break;
                }

                for(sal_uInt32 a(0L); a < aHairLinePolyPolygon.count(); a++)
                {
                    basegfx::B2DPolygon aCandidate = aHairLinePolyPolygon.getB2DPolygon(a);
                    basegfx::B2DPolyPolygon aAreaPolyPolygon = basegfx::tools::createAreaGeometryForPolygon(
                        aCandidate,
                        (double)mrLineAttr.GetDisplayLineWidth() / 2.0,
                        aB2DLineJoin,
                        (double)mrLineAttr.GetDegreeStepWidth() * F_PI180,
                        (double)mrLineAttr.GetLinejointMiterMinimumAngle() * F_PI180);
                    maAreaPolyPolygon.append(aAreaPolyPolygon);
                }
            }
        }
    }
}

// eof
<commit_msg>INTEGRATION: CWS vgbugs07 (1.6.254); FILE MERGED 2007/06/04 13:27:27 vg 1.6.254.1: #i76605# Remove -I .../inc/module hack introduced by hedaburemove01<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: svdoimp.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: hr $ $Date: 2007-06-27 19:06:36 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

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

#ifndef _SVX_SVDOIMP_HXX
#include <svdoimp.hxx>
#endif

#ifndef _SFXITEMSET_HXX
#include <svtools/itemset.hxx>
#endif

#ifndef _SVX_XLNSTIT_HXX
#include <svx/xlnstit.hxx>
#endif

#ifndef _SVX_XLNEDIT_HXX
#include <svx/xlnedit.hxx>
#endif

#ifndef _SVX_XLNWTIT_HXX
#include <svx/xlnwtit.hxx>
#endif

#ifndef _SVX_XLINEIT0_HXX
#include <svx/xlineit0.hxx>
#endif

#ifndef _SVX_XLNSTWIT_HXX
#include <svx/xlnstwit.hxx>
#endif

#ifndef _SVX_XLNEDWIT_HXX
#include <svx/xlnedwit.hxx>
#endif

#ifndef _SVX_XLNSTCIT_HXX
#include <svx/xlnstcit.hxx>
#endif

#ifndef _SVX_XLNEDCIT_HXX
#include <svx/xlnedcit.hxx>
#endif

#ifndef _SVX_XLINJOIT_HXX
#include <xlinjoit.hxx>
#endif

#ifndef _SVX_XLNDSIT_HXX
#include <svx/xlndsit.hxx>
#endif

#ifndef _BGFX_POLYGON_B2DPOLYGON_HXX
#include <basegfx/polygon/b2dpolygon.hxx>
#endif

#ifndef _BGFX_POINT_B2DPOINT_HXX
#include <basegfx/point/b2dpoint.hxx>
#endif

#ifndef _BGFX_VECTOR_B2DVECTOR_HXX
#include <basegfx/vector/b2dvector.hxx>
#endif

#ifndef _BGFX_RANGE_B2DRANGE_HXX
#include <basegfx/range/b2drange.hxx>
#endif

#ifndef _BGFX_POLYGON_B2DPOLYGONTOOLS_HXX
#include <basegfx/polygon/b2dpolygontools.hxx>
#endif

#ifndef _BGFX_MATRIX_B2DHOMMATRIX_HXX
#include <basegfx/matrix/b2dhommatrix.hxx>
#endif

#ifndef _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX
#include <basegfx/polygon/b2dpolypolygontools.hxx>
#endif

#ifndef _BGFX_POLYGON_B2DLINEGEOMETRY_HXX
#include <basegfx/polygon/b2dlinegeometry.hxx>
#endif

///////////////////////////////////////////////////////////////////////////////

ImpLineStyleParameterPack::ImpLineStyleParameterPack(
    const SfxItemSet& rSet,
    bool _bForceHair)
:   mbForceNoArrowsLeft(false),
    mbForceNoArrowsRight(false),
    mbForceHair(_bForceHair)
{
    maStartPolyPolygon = ((const XLineStartItem&)(rSet.Get(XATTR_LINESTART))).GetLineStartValue();

    if(maStartPolyPolygon.count())
    {
        if(maStartPolyPolygon.areControlPointsUsed())
        {
            maStartPolyPolygon = basegfx::tools::adaptiveSubdivideByAngle(maStartPolyPolygon);
        }

        if(basegfx::ORIENTATION_NEGATIVE == basegfx::tools::getOrientation(maStartPolyPolygon.getB2DPolygon(0L)))
        {
            maStartPolyPolygon.flip();
        }
    }

    maEndPolyPolygon = ((const XLineEndItem&)(rSet.Get(XATTR_LINEEND))).GetLineEndValue();

    if(maEndPolyPolygon.count())
    {
        if(maEndPolyPolygon.areControlPointsUsed())
        {
            maEndPolyPolygon = basegfx::tools::adaptiveSubdivideByAngle(maEndPolyPolygon);
        }

        if(basegfx::ORIENTATION_NEGATIVE == basegfx::tools::getOrientation(maEndPolyPolygon.getB2DPolygon(0L)))
        {
            maEndPolyPolygon.flip();
        }
    }

    mnLineWidth = ((const XLineWidthItem&)(rSet.Get(XATTR_LINEWIDTH))).GetValue();
    mbLineStyleSolid = (XLINE_SOLID == (XLineStyle)((const XLineStyleItem&)rSet.Get(XATTR_LINESTYLE)).GetValue());

    mnStartWidth = ((const XLineStartWidthItem&)(rSet.Get(XATTR_LINESTARTWIDTH))).GetValue();
    if(mnStartWidth < 0)
        mnStartWidth = -mnLineWidth * mnStartWidth / 100L;

    mnEndWidth = ((const XLineEndWidthItem&)(rSet.Get(XATTR_LINEENDWIDTH))).GetValue();
    if(mnEndWidth < 0)
        mnEndWidth = -mnLineWidth * mnEndWidth / 100L;

    mbStartCentered = ((const XLineStartCenterItem&)(rSet.Get(XATTR_LINESTARTCENTER))).GetValue();
    mbEndCentered = ((const XLineEndCenterItem&)(rSet.Get(XATTR_LINEENDCENTER))).GetValue();

    mfDegreeStepWidth = 10.0;
    meLineJoint = ((const XLineJointItem&)(rSet.Get(XATTR_LINEJOINT))).GetValue();

    XDash aDash = ((const XLineDashItem&)(rSet.Get(XATTR_LINEDASH))).GetDashValue();

    // fill local dash info
    mfFullDotDashLen = aDash.CreateDotDashArray(maDotDashArray, (double)GetDisplayLineWidth());
}

ImpLineStyleParameterPack::~ImpLineStyleParameterPack()
{
}

bool ImpLineStyleParameterPack::IsStartActive() const
{
    if(!mbForceNoArrowsLeft && maStartPolyPolygon.count() && GetStartWidth())
    {
        return (0L != maStartPolyPolygon.getB2DPolygon(0L).count());
    }

    return false;
}

bool ImpLineStyleParameterPack::IsEndActive() const
{
    if(!mbForceNoArrowsRight && maEndPolyPolygon.count() && GetEndWidth())
    {
        return (0L != maEndPolyPolygon.getB2DPolygon(0L).count());
    }

    return false;
}

void ImpLineGeometryCreator::ImpCreateLineGeometry(const basegfx::B2DPolygon& rSourcePoly)
{
    if(rSourcePoly.count() > 1L)
    {
        basegfx::B2DPolygon aSourceLineGeometry(rSourcePoly);

        if(aSourceLineGeometry.areControlPointsUsed())
        {
            aSourceLineGeometry = basegfx::tools::adaptiveSubdivideByAngle(aSourceLineGeometry);
        }

        sal_uInt32 nCount(aSourceLineGeometry.count());

        if(!aSourceLineGeometry.isClosed())
        {
            nCount--;
            const double fPolyLength(basegfx::tools::getLength(aSourceLineGeometry));
            double fStart(0.0);
            double fEnd(0.0);

            if(mrLineAttr.IsStartActive())
            {
                // create line start polygon and move line end
                basegfx::B2DPolyPolygon aArrowPolyPolygon;
                aArrowPolyPolygon.append(mrLineAttr.GetStartPolyPolygon());

                basegfx::B2DPolyPolygon aArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
                    aSourceLineGeometry,
                    aArrowPolyPolygon,
                    true,
                    (double)mrLineAttr.GetStartWidth(),
                    mrLineAttr.IsStartCentered() ? 0.5 : 0.0,
                    &fStart);

                maAreaPolyPolygon.append(aArrow);
                fStart *= 0.8;
            }

            if(mrLineAttr.IsEndActive())
            {
                // create line end polygon and move line end
                basegfx::B2DPolyPolygon aArrowPolyPolygon;
                aArrowPolyPolygon.append(mrLineAttr.GetEndPolyPolygon());

                basegfx::B2DPolyPolygon aArrow = basegfx::tools::createAreaGeometryForLineStartEnd(
                    aSourceLineGeometry,
                    aArrowPolyPolygon,
                    false,
                    (double)mrLineAttr.GetEndWidth(),
                    mrLineAttr.IsEndCentered() ? 0.5 : 0.0,
                    &fEnd);

                maAreaPolyPolygon.append(aArrow);
                fEnd *= 0.8;
            }

            if(fStart != 0.0 || fEnd != 0.0)
            {
                // build new poly, consume something from old poly
                aSourceLineGeometry = basegfx::tools::getSnippetAbsolute(
                    aSourceLineGeometry, fStart, fPolyLength - fEnd, fPolyLength);
                nCount = aSourceLineGeometry.count() - 1L;
            }
        }

        if(nCount)
        {
            basegfx::B2DPolyPolygon aHairLinePolyPolygon;

            if(mbLineDraft || mrLineAttr.IsLineStyleSolid())
            {
                // no LineStyle
                aHairLinePolyPolygon.append(aSourceLineGeometry);
            }
            else
            {
                // apply LineStyle
                aHairLinePolyPolygon = basegfx::tools::applyLineDashing(aSourceLineGeometry, mrLineAttr.GetDotDash(), mrLineAttr.GetFullDotDashLen());

                // merge LineStyle polygons to bigger parts
                aHairLinePolyPolygon = basegfx::tools::mergeDashedLines(aHairLinePolyPolygon);
            }

            if(!mrLineAttr.GetDisplayLineWidth())
            {
                // LineWidth zero, add directly to linePoly
                maLinePolyPolygon.append(aHairLinePolyPolygon);
            }
            else
            {
                basegfx::tools::B2DLineJoin aB2DLineJoin(basegfx::tools::B2DLINEJOIN_NONE);

                switch(mrLineAttr.GetLineJoint())
                {
                case XLINEJOINT_NONE    : aB2DLineJoin = basegfx::tools::B2DLINEJOIN_NONE;  break;
                case XLINEJOINT_MIDDLE  : aB2DLineJoin = basegfx::tools::B2DLINEJOIN_MIDDLE;    break;
                case XLINEJOINT_BEVEL   : aB2DLineJoin = basegfx::tools::B2DLINEJOIN_BEVEL; break;
                case XLINEJOINT_MITER   : aB2DLineJoin = basegfx::tools::B2DLINEJOIN_MITER; break;
                case XLINEJOINT_ROUND   : aB2DLineJoin = basegfx::tools::B2DLINEJOIN_ROUND; break;
                }

                for(sal_uInt32 a(0L); a < aHairLinePolyPolygon.count(); a++)
                {
                    basegfx::B2DPolygon aCandidate = aHairLinePolyPolygon.getB2DPolygon(a);
                    basegfx::B2DPolyPolygon aAreaPolyPolygon = basegfx::tools::createAreaGeometryForPolygon(
                        aCandidate,
                        (double)mrLineAttr.GetDisplayLineWidth() / 2.0,
                        aB2DLineJoin,
                        (double)mrLineAttr.GetDegreeStepWidth() * F_PI180,
                        (double)mrLineAttr.GetLinejointMiterMinimumAngle() * F_PI180);
                    maAreaPolyPolygon.append(aAreaPolyPolygon);
                }
            }
        }
    }
}

// eof
<|endoftext|>