odin-blend2d

Odin bindings to Blend2D
Log | Files | Refs | README | LICENSE

compopinfo.cpp (6754B)


      1 // This file is part of Blend2D project <https://blend2d.com>
      2 //
      3 // See blend2d.h or LICENSE.md for license and copyright information
      4 // SPDX-License-Identifier: Zlib
      5 
      6 #include "api-build_p.h"
      7 #include "compopinfo_p.h"
      8 #include "compopsimplifyimpl_p.h"
      9 
     10 namespace bl {
     11 
     12 struct CompOpInfoGen {
     13   #define F(VALUE) CompOpFlags::VALUE
     14 
     15   static constexpr CompOpInfo value(size_t op) noexcept {
     16     return CompOpInfo { uint16_t(
     17       op == size_t(CompOpExt::kSrcOver)     ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     18       op == size_t(CompOpExt::kSrcCopy)     ? F(kTypeB) | F(kNone) | F(kNone) | F(kSc)   | F(kSa)   | F(kNone)       | F(kNone)       :
     19       op == size_t(CompOpExt::kSrcIn)       ? F(kTypeB) | F(kNone) | F(kDa)   | F(kSc)   | F(kSa)   | F(kNopIfDaEq0) | F(kNone)       :
     20       op == size_t(CompOpExt::kSrcOut)      ? F(kTypeB) | F(kNone) | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNone)       :
     21       op == size_t(CompOpExt::kSrcAtop)     ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNopIfDaEq0) | F(kNopIfSaEq0) :
     22       op == size_t(CompOpExt::kDstOver)     ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNopIfDaEq1) | F(kNopIfSaEq0) :
     23       op == size_t(CompOpExt::kDstCopy)     ? F(kTypeC) | F(kDc)   | F(kDa)   | F(kNone) | F(kNone) | F(kNop)        | F(kNop)        :
     24       op == size_t(CompOpExt::kDstIn)       ? F(kTypeB) | F(kDc)   | F(kDa)   | F(kNone) | F(kSa)   | F(kNone)       | F(kNopIfSaEq1) :
     25       op == size_t(CompOpExt::kDstOut)      ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kNone) | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     26       op == size_t(CompOpExt::kDstAtop)     ? F(kTypeB) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNone)       :
     27       op == size_t(CompOpExt::kXor)         ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     28       op == size_t(CompOpExt::kClear)       ? F(kTypeC) | F(kNone) | F(kNone) | F(kNone) | F(kNone) | F(kNopIfDaEq0) | F(kNone)       :
     29 
     30       op == size_t(CompOpExt::kPlus)        ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     31       op == size_t(CompOpExt::kMinus)       ? F(kTypeC) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     32       op == size_t(CompOpExt::kModulate)    ? F(kTypeB) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNopIfDaEq0) | F(kNone)       :
     33       op == size_t(CompOpExt::kMultiply)    ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNopIfDaEq0) | F(kNopIfSaEq0) :
     34       op == size_t(CompOpExt::kScreen)      ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     35       op == size_t(CompOpExt::kOverlay)     ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     36       op == size_t(CompOpExt::kDarken)      ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     37       op == size_t(CompOpExt::kLighten)     ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     38       op == size_t(CompOpExt::kColorDodge)  ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     39       op == size_t(CompOpExt::kColorBurn)   ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     40       op == size_t(CompOpExt::kLinearBurn)  ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     41       op == size_t(CompOpExt::kLinearLight) ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     42       op == size_t(CompOpExt::kPinLight)    ? F(kTypeC) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     43       op == size_t(CompOpExt::kHardLight)   ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     44       op == size_t(CompOpExt::kSoftLight)   ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     45       op == size_t(CompOpExt::kDifference)  ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     46       op == size_t(CompOpExt::kExclusion)   ? F(kTypeA) | F(kDc)   | F(kDa)   | F(kSc)   | F(kSa)   | F(kNone)       | F(kNopIfSaEq0) :
     47 
     48       op == size_t(CompOpExt::kAlphaInv)    ? F(kTypeC) | F(kNone) | F(kDa)   | F(kNone) | F(kNone) | F(kNone)       | F(kNone)       : F(kNone)
     49     ) };
     50   }
     51 
     52   #undef F
     53 };
     54 
     55 const LookupTable<CompOpInfo, uint32_t(CompOpExt::kMaxValue) + 1> comp_op_info_table =
     56   make_lookup_table<CompOpInfo, uint32_t(CompOpExt::kMaxValue) + 1, CompOpInfoGen>();
     57 
     58 struct CompOpSimplifyInfoGen {
     59   // Function called by the table generator, decomposes the parameters and passes them to the simplifier.
     60   static constexpr CompOpSimplifyInfo value(size_t index) noexcept {
     61     return CompOpSimplifyInfoImpl::simplify(
     62       CompOpExt(uint32_t((index / kFormatExtCount)) % kCompOpExtCount),
     63       FormatExt(index / (kCompOpExtCount * kFormatExtCount)),
     64       FormatExt(index % kFormatExtCount));
     65   }
     66 };
     67 
     68 template<bl::FormatExt Dst>
     69 struct CompOpSimplifyInfoRecordSetGen {
     70   // Function called by the table generator, decomposes the parameters and passes them to the simplifier.
     71   static constexpr CompOpSimplifyInfo value(size_t index) noexcept {
     72     return CompOpSimplifyInfoImpl::simplify(CompOpExt(index / kFormatExtCount), Dst, FormatExt(index % kFormatExtCount));
     73   }
     74 };
     75 
     76 static_assert(BL_FORMAT_MAX_VALUE == 3u, "Don't forget to add new formats to comp_op_simplify_info_table");
     77 
     78 // HACK: MSVC doesn't honor constexpr functions and sometimes outputs initialization
     79 //       code even when the expression can be calculated at compile time. To fix this
     80 //       we go through an additional constexpr to force the compiler to always generate
     81 //       our lookup tables at compile time.
     82 //
     83 // Additionally, if there is a mistake leading to recursion the compiler would catch it
     84 // at compile-time instead of hitting it at runtime during initialization.
     85 static constexpr const CompOpSimplifyInfoTable comp_op_simplify_info_table_ = {{
     86   make_lookup_table<CompOpSimplifyInfo, kCompOpSimplifyRecordSize, CompOpSimplifyInfoRecordSetGen<FormatExt(0)>>(),
     87   make_lookup_table<CompOpSimplifyInfo, kCompOpSimplifyRecordSize, CompOpSimplifyInfoRecordSetGen<FormatExt(1)>>(),
     88   make_lookup_table<CompOpSimplifyInfo, kCompOpSimplifyRecordSize, CompOpSimplifyInfoRecordSetGen<FormatExt(2)>>(),
     89   make_lookup_table<CompOpSimplifyInfo, kCompOpSimplifyRecordSize, CompOpSimplifyInfoRecordSetGen<FormatExt(3)>>()
     90 }};
     91 const CompOpSimplifyInfoTable comp_op_simplify_info_table = comp_op_simplify_info_table_;
     92 
     93 } // {bl}