diff options
author | Noel Grandin <noel@peralex.com> | 2014-10-06 14:48:16 +0200 |
---|---|---|
committer | Stephan Bergmann <sbergman@redhat.com> | 2014-10-13 17:45:57 +0200 |
commit | af5ebbf7835441c767f91a620f109ee6722e57bd (patch) | |
tree | c72b2a1ddb5aa0a0a369be7babd516a5592d5fac /include | |
parent | 1156d11ef0bb2bc3d71ae9299656db4fed66f073 (diff) |
create a macro library for implementing bit-flags types
Signed-off-by: Stephan Bergmann <sbergman@redhat.com>,
changed from a macro- to a template-based solution. (Unfortunately MSVC 2012
does not support explicit conversion operators. Worked around that with
explicit #ifs rather than some HAVE_EXPLICIT_CONVERSION_OPERATORS and
SAL_EXPLICIT_CONVERSION_OPERATOR ainticipating we hopefully soon move to a
baseline that requires unconditional support for them.)
Change-Id: I4a89643b218d247e8e4a861faba458ec6dfe1396
Diffstat (limited to 'include')
-rw-r--r-- | include/o3tl/typed_flags_set.hxx | 208 | ||||
-rw-r--r-- | include/vcl/outdev.hxx | 2 | ||||
-rw-r--r-- | include/vcl/outdevstate.hxx | 57 | ||||
-rw-r--r-- | include/vcl/pdfwriter.hxx | 2 |
4 files changed, 238 insertions, 31 deletions
diff --git a/include/o3tl/typed_flags_set.hxx b/include/o3tl/typed_flags_set.hxx new file mode 100644 index 000000000000..baa679354de5 --- /dev/null +++ b/include/o3tl/typed_flags_set.hxx @@ -0,0 +1,208 @@ +/* -*- 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_O3TL_TYPED_FLAGS_SET_HXX +#define INCLUDED_O3TL_TYPED_FLAGS_SET_HXX + +#include <sal/config.h> + +#include <cassert> +#include <type_traits> + +namespace o3tl { + +template<typename T> struct typed_flags {}; + +/// Mark a (scoped) enumeration as a set of bit flags, with accompanying +/// operations. +/// +/// template<> +/// struct o3tl::typed_flags<TheE>: o3tl::is_typed_flags<TheE, TheM> {}; +/// +/// All relevant values must be non-negative. (Typically, the enumeration's +/// underlying type will either be fixed and unsigned, or it will be unfixed--- +/// and can thus default to a signed type---and all enumerators will have non- +/// negative values.) +/// +/// \param E the enumeration type. +/// \param M the all-bits-set value for the bit flags. +template<typename E, typename std::underlying_type<E>::type M> +struct is_typed_flags { + static_assert( + M >= 0, "is_typed_flags expects only non-negative bit values"); + + class Self { + public: + explicit Self(typename std::underlying_type<E>::type value): + value_(value) + { assert(value >= 0); } + + operator E() { return static_cast<E>(value_); } + +#if !defined _MSC_VER || _MSC_VER > 1700 + explicit +#endif + operator typename std::underlying_type<E>::type() { return value_; } + +#if !defined _MSC_VER || _MSC_VER > 1700 + explicit +#endif + operator bool() { return value_ != 0; } + + private: + typename std::underlying_type<E>::type value_; + }; + + static typename std::underlying_type<E>::type const mask = M; +}; + +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator ~(E rhs) { + assert(static_cast<typename std::underlying_type<E>::type>(rhs) >= 0); + return static_cast<typename o3tl::typed_flags<E>::Self>( + o3tl::typed_flags<E>::mask + & ~static_cast<typename std::underlying_type<E>::type>(rhs)); +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator ~( + typename o3tl::typed_flags<E>::Self rhs) +{ + return static_cast<typename o3tl::typed_flags<E>::Self>( + o3tl::typed_flags<E>::mask + & ~static_cast<typename std::underlying_type<E>::type>(rhs)); +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator &(E lhs, E rhs) { + assert(static_cast<typename std::underlying_type<E>::type>(lhs) >= 0); + assert(static_cast<typename std::underlying_type<E>::type>(rhs) >= 0); + return static_cast<typename o3tl::typed_flags<E>::Self>( + static_cast<typename std::underlying_type<E>::type>(lhs) + & static_cast<typename std::underlying_type<E>::type>(rhs)); +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator &( + E lhs, typename o3tl::typed_flags<E>::Self rhs) +{ + assert(static_cast<typename std::underlying_type<E>::type>(lhs) >= 0); + return static_cast<typename o3tl::typed_flags<E>::Self>( + static_cast<typename std::underlying_type<E>::type>(lhs) + & static_cast<typename std::underlying_type<E>::type>(rhs)); +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator &( + typename o3tl::typed_flags<E>::Self lhs, E rhs) +{ + assert(static_cast<typename std::underlying_type<E>::type>(rhs) >= 0); + return static_cast<typename o3tl::typed_flags<E>::Self>( + static_cast<typename std::underlying_type<E>::type>(lhs) + & static_cast<typename std::underlying_type<E>::type>(rhs)); +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator &( + typename o3tl::typed_flags<E>::Self lhs, + typename o3tl::typed_flags<E>::Self rhs) +{ + return static_cast<typename o3tl::typed_flags<E>::Self>( + static_cast<typename std::underlying_type<E>::type>(lhs) + & static_cast<typename std::underlying_type<E>::type>(rhs)); +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator |(E lhs, E rhs) { + assert(static_cast<typename std::underlying_type<E>::type>(lhs) >= 0); + assert(static_cast<typename std::underlying_type<E>::type>(rhs) >= 0); + return static_cast<typename o3tl::typed_flags<E>::Self>( + static_cast<typename std::underlying_type<E>::type>(lhs) + | static_cast<typename std::underlying_type<E>::type>(rhs)); +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator |( + E lhs, typename o3tl::typed_flags<E>::Self rhs) +{ + assert(static_cast<typename std::underlying_type<E>::type>(lhs) >= 0); + return static_cast<typename o3tl::typed_flags<E>::Self>( + static_cast<typename std::underlying_type<E>::type>(lhs) + | static_cast<typename std::underlying_type<E>::type>(rhs)); +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator |( + typename o3tl::typed_flags<E>::Self lhs, E rhs) +{ + assert(static_cast<typename std::underlying_type<E>::type>(rhs) >= 0); + return static_cast<typename o3tl::typed_flags<E>::Self>( + static_cast<typename std::underlying_type<E>::type>(lhs) + | static_cast<typename std::underlying_type<E>::type>(rhs)); +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator |( + typename o3tl::typed_flags<E>::Self lhs, + typename o3tl::typed_flags<E>::Self rhs) +{ + return static_cast<typename o3tl::typed_flags<E>::Self>( + static_cast<typename std::underlying_type<E>::type>(lhs) + | static_cast<typename std::underlying_type<E>::type>(rhs)); +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator &=(E & lhs, E rhs) { + assert(static_cast<typename std::underlying_type<E>::type>(lhs) >= 0); + assert(static_cast<typename std::underlying_type<E>::type>(rhs) >= 0); + lhs = lhs & rhs; + return lhs; +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator &=( + E & lhs, typename o3tl::typed_flags<E>::Self rhs) +{ + assert(static_cast<typename std::underlying_type<E>::type>(lhs) >= 0); + lhs = lhs & rhs; + return lhs; +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator |=(E & lhs, E rhs) { + assert(static_cast<typename std::underlying_type<E>::type>(lhs) >= 0); + assert(static_cast<typename std::underlying_type<E>::type>(rhs) >= 0); + lhs = lhs | rhs; + return lhs; +} + +template<typename E> +inline typename o3tl::typed_flags<E>::Self operator |=( + E & lhs, typename o3tl::typed_flags<E>::Self rhs) +{ + assert(static_cast<typename std::underlying_type<E>::type>(lhs) >= 0); + lhs = lhs | rhs; + return lhs; +} + +#endif /* INCLUDED_O3TL_TYPED_FLAGS_SET_HXX */ + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index c90f09d8820c..d87100afe8f4 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -537,7 +537,7 @@ private: public: - void Push( PushFlags nFlags = PUSH_ALL ); + void Push( PushFlags nFlags = PushFlags::ALL ); void Pop(); // returns the current stack depth; that is the number of Push() calls minus the number of Pop() calls diff --git a/include/vcl/outdevstate.hxx b/include/vcl/outdevstate.hxx index 9b2811a86a6a..da3dc4e0b050 100644 --- a/include/vcl/outdevstate.hxx +++ b/include/vcl/outdevstate.hxx @@ -30,38 +30,35 @@ #include <tools/gen.hxx> #include <tools/color.hxx> #include <tools/fontenum.hxx> +#include <o3tl/typed_flags_set.hxx> // Flags for OutputDevice::Push() and OutDevState -enum PushFlags { - PUSH_NONE = ((sal_uInt16)0x0000), - PUSH_LINECOLOR = ((sal_uInt16)0x0001), - PUSH_FILLCOLOR = ((sal_uInt16)0x0002), - PUSH_FONT = ((sal_uInt16)0x0004), - PUSH_TEXTCOLOR = ((sal_uInt16)0x0008), - PUSH_MAPMODE = ((sal_uInt16)0x0010), - PUSH_CLIPREGION = ((sal_uInt16)0x0020), - PUSH_RASTEROP = ((sal_uInt16)0x0040), - PUSH_TEXTFILLCOLOR = ((sal_uInt16)0x0080), - PUSH_TEXTALIGN = ((sal_uInt16)0x0100), - PUSH_REFPOINT = ((sal_uInt16)0x0200), - PUSH_TEXTLINECOLOR = ((sal_uInt16)0x0400), - PUSH_TEXTLAYOUTMODE = ((sal_uInt16)0x0800), - PUSH_TEXTLANGUAGE = ((sal_uInt16)0x1000), - PUSH_OVERLINECOLOR = ((sal_uInt16)0x2000), - PUSH_ALL = ((sal_uInt16)0xFFFF) +enum class PushFlags : sal_uInt16 { + NONE = 0x0000, + LINECOLOR = 0x0001, + FILLCOLOR = 0x0002, + FONT = 0x0004, + TEXTCOLOR = 0x0008, + MAPMODE = 0x0010, + CLIPREGION = 0x0020, + RASTEROP = 0x0040, + TEXTFILLCOLOR = 0x0080, + TEXTALIGN = 0x0100, + REFPOINT = 0x0200, + TEXTLINECOLOR = 0x0400, + TEXTLAYOUTMODE = 0x0800, + TEXTLANGUAGE = 0x1000, + OVERLINECOLOR = 0x2000, + ALL = 0xFFFF + + //bool operator bool() { return static_cast<sal_uInt16>(*this) != 0; } }; -// make combining these type-safe -inline PushFlags operator| (PushFlags lhs, PushFlags rhs) -{ - return static_cast<PushFlags>(static_cast<sal_uInt16>(lhs) | static_cast<sal_uInt16>(rhs)); -} -inline PushFlags operator& (PushFlags lhs, PushFlags rhs) -{ - return static_cast<PushFlags>(static_cast<sal_uInt16>(lhs) & static_cast<sal_uInt16>(rhs)); -} +template<> +struct o3tl::typed_flags<PushFlags>: o3tl::is_typed_flags<PushFlags, 0xFFFF> {}; +#define PUSH_ALLTEXT (PushFlags::TEXTCOLOR | PushFlags::TEXTFILLCOLOR | PushFlags::TEXTLINECOLOR | PushFlags::OVERLINECOLOR | PushFlags::TEXTALIGN | PushFlags::TEXTLAYOUTMODE | PushFlags::TEXTLANGUAGE) +#define PUSH_ALLFONT (PUSH_ALLTEXT | PushFlags::FONT) + -#define PUSH_ALLTEXT (PUSH_TEXTCOLOR | PUSH_TEXTFILLCOLOR | PUSH_TEXTLINECOLOR | PUSH_OVERLINECOLOR | PUSH_TEXTALIGN | PUSH_TEXTLAYOUTMODE | PUSH_TEXTLANGUAGE) -#define PUSH_ALLFONT (PUSH_ALLTEXT | PUSH_FONT) // LayoutModes for Complex Text Layout // These are flag values, i.e they can be combined @@ -101,6 +98,8 @@ inline ComplexTextLayoutMode& operator&= (ComplexTextLayoutMode& lhs, ComplexTex } + + class OutDevState { public: @@ -108,7 +107,7 @@ public: MapMode* mpMapMode; bool mbMapActive; - vcl::Region* mpClipRegion; + vcl::Region* mpClipRegion; Color* mpLineColor; Color* mpFillColor; vcl::Font* mpFont; diff --git a/include/vcl/pdfwriter.hxx b/include/vcl/pdfwriter.hxx index 03211f42aa80..880e2fa30949 100644 --- a/include/vcl/pdfwriter.hxx +++ b/include/vcl/pdfwriter.hxx @@ -729,7 +729,7 @@ The following structure describes the permissions used in PDF security /* functions for graphics state */ /* flag values: see vcl/outdev.hxx */ - void Push( PushFlags nFlags = PUSH_ALL ); + void Push( PushFlags nFlags = PushFlags::ALL ); void Pop(); void SetClipRegion(); |