/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project .
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License , v . 2 . 0 . If a copy of the MPL was not distributed with this
* file , You can obtain one at http : //mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice :
*
* Licensed to the Apache Software Foundation ( ASF ) under one or more
* contributor license agreements . See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership . The ASF licenses this file to you 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 .
*/
#ifndef INCLUDED_OOX_HELPER_HELPER_HXX
#define INCLUDED_OOX_HELPER_HELPER_HXX
#include <sal/config.h>
#include <cstring>
#include <limits>
#include <optional>
#include <o3tl/safeint.hxx>
#include <osl/endian.h>
#include <rtl/math.hxx>
#include <sal/macros.h>
#include <sal/types.h>
#include <tools/color.hxx>
namespace oox {
// Helper macros ==============================================================
namespace detail {
//TODO: Temporary helper for STATIC_ARRAY_SELECT; ultimately, the latter should be replaced by a
// proper function (template):
template <typename T> constexpr std::make_unsigned_t<T> make_unsigned(T value) {
if constexpr (std::is_signed_v<T>) {
return o3tl::make_unsigned(value);
} else {
return value;
}
}
}
/** Expands to the 'index'-th element of a STATIC data array, or to 'def', if
'index' is out of the array limits. */
#define STATIC_ARRAY_SELECT( array, index, def ) \
((detail::make_unsigned(index) < std::size(array)) ? ((array)[static_cast <size_t>(index)]) : (def))
// Common constants ===========================================================
const sal_uInt8 WINDOWS_CHARSET_ANSI = 0 ;
const sal_uInt8 WINDOWS_CHARSET_DEFAULT = 1 ;
const sal_uInt8 WINDOWS_CHARSET_SYMBOL = 2 ;
const sal_uInt8 WINDOWS_CHARSET_APPLE_ROMAN = 77 ;
const sal_uInt8 WINDOWS_CHARSET_SHIFTJIS = 128 ;
const sal_uInt8 WINDOWS_CHARSET_HANGEUL = 129 ;
const sal_uInt8 WINDOWS_CHARSET_JOHAB = 130 ;
const sal_uInt8 WINDOWS_CHARSET_GB2312 = 134 ;
const sal_uInt8 WINDOWS_CHARSET_BIG5 = 136 ;
const sal_uInt8 WINDOWS_CHARSET_GREEK = 161 ;
const sal_uInt8 WINDOWS_CHARSET_TURKISH = 162 ;
const sal_uInt8 WINDOWS_CHARSET_VIETNAMESE = 163 ;
const sal_uInt8 WINDOWS_CHARSET_HEBREW = 177 ;
const sal_uInt8 WINDOWS_CHARSET_ARABIC = 178 ;
const sal_uInt8 WINDOWS_CHARSET_BALTIC = 186 ;
const sal_uInt8 WINDOWS_CHARSET_RUSSIAN = 204 ;
const sal_uInt8 WINDOWS_CHARSET_THAI = 222 ;
const sal_uInt8 WINDOWS_CHARSET_EASTERN = 238 ;
const sal_uInt8 WINDOWS_CHARSET_OEM = 255 ;
const ::Color API_RGB_TRANSPARENT (ColorTransparency, 0 xffffffff); ///< Transparent color for API calls.
const sal_uInt32 UNSIGNED_RGB_TRANSPARENT = static_cast <sal_uInt32>(-1 ); ///< Transparent color for unsigned int32 places.
const ::Color API_RGB_BLACK (0 x000000); ///< Black color for API calls.
const ::Color API_RGB_GRAY (0 x808080); ///< Gray color for API calls.
const ::Color API_RGB_WHITE (0 xFFFFFF); ///< White color for API calls.
const sal_Int16 API_LINE_SOLID = 0 ;
const sal_Int16 API_LINE_DOTTED = 1 ;
const sal_Int16 API_LINE_DASHED = 2 ;
const sal_Int16 API_FINE_LINE_DASHED = 14 ;
const sal_Int16 API_LINE_NONE = 0 ;
const sal_Int16 API_LINE_HAIR = 2 ;
const sal_Int16 API_LINE_THIN = 35 ;
const sal_Int16 API_LINE_MEDIUM = 88 ;
const sal_Int16 API_LINE_THICK = 141 ;
const sal_Int16 API_ESCAPE_NONE = 0 ; ///< No escapement.
const sal_Int16 API_ESCAPE_SUPERSCRIPT = 101 ; ///< Superscript: raise characters automatically (magic value 101).
const sal_Int16 API_ESCAPE_SUBSCRIPT = -101 ; ///< Subscript: lower characters automatically (magic value -101).
const sal_Int8 API_ESCAPEHEIGHT_NONE = 100 ; ///< Relative character height if not escaped.
const sal_Int8 API_ESCAPEHEIGHT_DEFAULT = 58 ; ///< Relative character height if escaped.
// Limitate values ------------------------------------------------------------
template < typename ReturnType, typename Type >
inline ReturnType getLimitedValue( Type nValue, Type nMin, Type nMax )
{
return static_cast < ReturnType >( ::std::clamp( nValue, nMin, nMax ) );
}
template < typename ReturnType, typename Type >
inline ReturnType getIntervalValue( Type nValue, Type nBegin, Type nEnd )
{
static_assert(::std::numeric_limits< Type >::is_integer, "is integer" );
Type nInterval = nEnd - nBegin;
Type nCount = (nValue < nBegin) ? -((nBegin - nValue - 1 ) / nInterval + 1 ) : ((nValue - nBegin) / nInterval);
return static_cast < ReturnType >( nValue - nCount * nInterval );
}
template < typename ReturnType >
inline ReturnType getDoubleIntervalValue( double fValue, double fBegin, double fEnd )
{
double fInterval = fEnd - fBegin;
double fCount = (fValue < fBegin) ? -(::rtl::math::approxFloor( (fBegin - fValue - 1 .0 ) / fInterval ) + 1 .0 ) : ::rtl::math::approxFloor( (fValue - fBegin) / fInterval );
return static_cast < ReturnType >( fValue - fCount * fInterval );
}
// Read from bitfields --------------------------------------------------------
/** Returns true, if at least one of the bits set in nMask is set in nBitField. */
template < typename Type >
inline bool getFlag( Type nBitField, Type nMask )
{
return (nBitField & nMask) != 0 ;
}
/** Returns nSet, if at least one bit of nMask is set in nBitField, otherwise nUnset. */
template < typename ReturnType, typename Type >
inline ReturnType getFlagValue( Type nBitField, Type nMask, ReturnType nSet, ReturnType nUnset )
{
return getFlag( nBitField, nMask ) ? nSet : nUnset;
}
/** Extracts a value from a bit field.
Returns the data fragment from nBitField , that starts at bit nStartBit
( 0 - based , bit 0 is rightmost ) with the width of nBitCount . The returned
value will be right - aligned ( normalized ) .
For instance : extractValue < T > ( 0 x4321 , 8 , 4 ) returns 3 ( value in bits 8 - 11 ) .
*/
template < typename ReturnType, typename Type >
inline ReturnType extractValue( Type nBitField, sal_uInt8 nStartBit, sal_uInt8 nBitCount )
{
sal_uInt64 nMask = 1 ; nMask <<= nBitCount; --nMask;
return static_cast < ReturnType >( nMask & (nBitField >> nStartBit) );
}
// Write to bitfields ---------------------------------------------------------
/** Sets or clears (according to bSet) all set bits of nMask in ornBitField. */
template < typename Type >
inline void setFlag( Type& ornBitField, Type nMask, bool bSet = true )
{
if ( bSet ) ornBitField |= nMask; else ornBitField &= ~nMask;
}
template < typename Type >
void assignIfUsed( std::optional<Type>& rDestValue, const std::optional<Type>& rSourceValue )
{
if ( rSourceValue.has_value() )
rDestValue = rSourceValue.value();
}
/** Provides platform independent functions to convert from or to little-endian
byte order , e . g . for reading data from or writing data to memory or a
binary stream .
On big - endian platforms , the byte order in the passed values is swapped ,
this can be used for converting big - endian to and from little - endian data .
On little - endian platforms , the conversion functions are implemented empty ,
thus compilers should completely optimize away the function call .
*/
class ByteOrderConverter
{
public :
#ifdef OSL_BIGENDIAN
static void convertLittleEndian( sal_Int8& ) {} // present for usage in templates
static void convertLittleEndian( sal_uInt8& ) {} // present for usage in templates
static void convertLittleEndian( char16_t& rnValue ) { swap2( reinterpret_cast < sal_uInt8* >( &rnValue ) ); }
static void convertLittleEndian( sal_Int16& rnValue ) { swap2( reinterpret_cast < sal_uInt8* >( &rnValue ) ); }
static void convertLittleEndian( sal_uInt16& rnValue ) { swap2( reinterpret_cast < sal_uInt8* >( &rnValue ) ); }
static void convertLittleEndian( sal_Int32& rnValue ) { swap4( reinterpret_cast < sal_uInt8* >( &rnValue ) ); }
static void convertLittleEndian( sal_uInt32& rnValue ) { swap4( reinterpret_cast < sal_uInt8* >( &rnValue ) ); }
static void convertLittleEndian( sal_Int64& rnValue ) { swap8( reinterpret_cast < sal_uInt8* >( &rnValue ) ); }
static void convertLittleEndian( sal_uInt64& rnValue ) { swap8( reinterpret_cast < sal_uInt8* >( &rnValue ) ); }
static void convertLittleEndian( float & rfValue ) { swap4( reinterpret_cast < sal_uInt8* >( &rfValue ) ); }
static void convertLittleEndian( double & rfValue ) { swap8( reinterpret_cast < sal_uInt8* >( &rfValue ) ); }
template < typename Type >
inline static void convertLittleEndianArray( Type* pnArray, size_t nElemCount );
static void convertLittleEndianArray( sal_Int8*, size_t ) {}
static void convertLittleEndianArray( sal_uInt8*, size_t ) {}
#else
template < typename Type >
static void convertLittleEndian( Type& ) {}
template < typename Type >
static void convertLittleEndianArray( Type*, size_t ) {}
#endif
/** Writes a value to memory, while converting it to little-endian.
@ param pDstBuffer The memory buffer to write the value to .
@ param nValue The value to be written to memory in little - endian .
*/
template < typename Type >
inline static void writeLittleEndian( void * pDstBuffer, Type nValue );
#ifdef OSL_BIGENDIAN
private :
inline static void swap2( sal_uInt8* pnData );
inline static void swap4( sal_uInt8* pnData );
inline static void swap8( sal_uInt8* pnData );
#endif
};
template < typename Type >
inline void ByteOrderConverter::writeLittleEndian( void * pDstBuffer, Type nValue )
{
convertLittleEndian( nValue );
memcpy( pDstBuffer, &nValue, sizeof ( Type ) );
}
#ifdef OSL_BIGENDIAN
template < typename Type >
inline void ByteOrderConverter::convertLittleEndianArray( Type* pnArray, size_t nElemCount )
{
for ( Type* pnArrayEnd = pnArray + nElemCount; pnArray != pnArrayEnd; ++pnArray )
convertLittleEndian( *pnArray );
}
inline void ByteOrderConverter::swap2( sal_uInt8* pnData )
{
::std::swap( pnData[ 0 ], pnData[ 1 ] );
}
inline void ByteOrderConverter::swap4( sal_uInt8* pnData )
{
::std::swap( pnData[ 0 ], pnData[ 3 ] );
::std::swap( pnData[ 1 ], pnData[ 2 ] );
}
inline void ByteOrderConverter::swap8( sal_uInt8* pnData )
{
::std::swap( pnData[ 0 ], pnData[ 7 ] );
::std::swap( pnData[ 1 ], pnData[ 6 ] );
::std::swap( pnData[ 2 ], pnData[ 5 ] );
::std::swap( pnData[ 3 ], pnData[ 4 ] );
}
#endif
} // namespace oox
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Messung V0.5 in Prozent C=89 H=99 G=94
¤ Dauer der Verarbeitung: 0.10 Sekunden
(vorverarbeitet am 2026-06-10)
¤
*© Formatika GbR, Deutschland