Compute inverse gamma table at compile time.
This introduces skstd::index_sequence and skstd::make_index_sequence so that these can be used in C++11. These are mostly equivalent to their std:: counterparts. This also introduces SkMakeArray<N, C> which is constexpr and creates a std::array with N elements with each element being initialized with the value of C(i) where i is the index of the element. These are then used to create inverse gamma table at compile time. This avoids threading issues. BUG=skia:7187 Change-Id: I61fb10a778898652e546d54c104a08d6e6bf88d3 Reviewed-on: https://skia-review.googlesource.com/61380 Commit-Queue: Ben Wagner <bungeman@google.com> Reviewed-by: Mike Klein <mtklein@chromium.org>
This commit is contained in:
parent
62cbb67a02
commit
7a0248f738
@ -14,6 +14,7 @@
|
||||
#ifndef SkTLogic_DEFINED
|
||||
#define SkTLogic_DEFINED
|
||||
|
||||
#include <array>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <type_traits>
|
||||
@ -39,6 +40,8 @@ template <typename T> using add_cv_t = typename std::add_cv<T>::type;
|
||||
template <typename T> using add_pointer_t = typename std::add_pointer<T>::type;
|
||||
template <typename T> using add_lvalue_reference_t = typename std::add_lvalue_reference<T>::type;
|
||||
|
||||
template <typename T> using result_of_t = typename std::result_of<T>::type;
|
||||
|
||||
template <typename... T> using common_type_t = typename std::common_type<T...>::type;
|
||||
|
||||
// Chromium currently requires gcc 4.8.2 or a recent clang compiler, but uses libstdc++4.6.4.
|
||||
@ -64,6 +67,25 @@ template <typename T> using is_trivially_destructible = std::is_trivially_destru
|
||||
#endif
|
||||
template <typename T> using underlying_type_t = typename skstd::underlying_type<T>::type;
|
||||
|
||||
|
||||
template <std::size_t... Ints> struct index_sequence {
|
||||
using type = index_sequence;
|
||||
using value_type = size_t;
|
||||
static constexpr std::size_t size() noexcept { return sizeof...(Ints); }
|
||||
};
|
||||
|
||||
template <typename S1, typename S2> struct make_index_sequence_combine;
|
||||
template <size_t... I1, size_t... I2>
|
||||
struct make_index_sequence_combine<skstd::index_sequence<I1...>, skstd::index_sequence<I2...>>
|
||||
: skstd::index_sequence<I1..., (sizeof...(I1)+I2)...>
|
||||
{ };
|
||||
|
||||
template <size_t N> struct make_index_sequence
|
||||
: make_index_sequence_combine<typename skstd::make_index_sequence< N/2>::type,
|
||||
typename skstd::make_index_sequence<N - N/2>::type>{};
|
||||
template<> struct make_index_sequence<0> : skstd::index_sequence< >{};
|
||||
template<> struct make_index_sequence<1> : skstd::index_sequence<0>{};
|
||||
|
||||
} // namespace skstd
|
||||
|
||||
// The sknonstd namespace contains things we would like to be proposed and feel std-ish.
|
||||
|
@ -483,4 +483,15 @@ private:
|
||||
|
||||
using SkAutoFree = std::unique_ptr<void, SkFunctionWrapper<void, void, sk_free>>;
|
||||
|
||||
template<typename C, std::size_t... Is>
|
||||
constexpr auto SkMakeArrayFromIndexSequence(C c, skstd::index_sequence<Is...>)
|
||||
-> std::array<skstd::result_of_t<C(std::size_t)>, sizeof...(Is)> {
|
||||
return {{ c(Is)... }};
|
||||
}
|
||||
|
||||
template<size_t N, typename C> constexpr auto SkMakeArray(C c)
|
||||
-> std::array<skstd::result_of_t<C(std::size_t)>, N> {
|
||||
return SkMakeArrayFromIndexSequence(c, skstd::make_index_sequence<N>{});
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1056,12 +1056,8 @@ void SkScalerContext_Mac::generateMetrics(SkGlyph* glyph) {
|
||||
|
||||
#include "SkColorData.h"
|
||||
|
||||
static void build_power_table(uint8_t table[]) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
float x = i / 255.f;
|
||||
int xx = SkScalarRoundToInt(x * x * 255);
|
||||
table[i] = SkToU8(xx);
|
||||
}
|
||||
static constexpr uint8_t sk_pow2_table(size_t i) {
|
||||
return SkToU8(((i * i + 128) / 255));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1071,15 +1067,7 @@ static void build_power_table(uint8_t table[]) {
|
||||
* CoreGraphics obscurely defaults to 2.0 as the smoothing gamma value.
|
||||
* The color space used does not appear to affect this choice.
|
||||
*/
|
||||
static const uint8_t* getInverseGammaTableCoreGraphicSmoothing() {
|
||||
static bool gInited;
|
||||
static uint8_t gTableCoreGraphicsSmoothing[256];
|
||||
if (!gInited) {
|
||||
build_power_table(gTableCoreGraphicsSmoothing);
|
||||
gInited = true;
|
||||
}
|
||||
return gTableCoreGraphicsSmoothing;
|
||||
}
|
||||
static constexpr auto gLinearCoverageFromCGLCDValue = SkMakeArray<256>(sk_pow2_table);
|
||||
|
||||
static void cgpixels_to_bits(uint8_t dst[], const CGRGBPixel src[], int count) {
|
||||
while (count > 0) {
|
||||
@ -1179,7 +1167,7 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
|
||||
if ((glyph.fMaskFormat == SkMask::kLCD16_Format) ||
|
||||
(glyph.fMaskFormat == SkMask::kA8_Format && supports_LCD() && generateA8FromLCD))
|
||||
{
|
||||
const uint8_t* table = getInverseGammaTableCoreGraphicSmoothing();
|
||||
const uint8_t* linear = gLinearCoverageFromCGLCDValue.data();
|
||||
|
||||
//Note that the following cannot really be integrated into the
|
||||
//pre-blend, since we may not be applying the pre-blend; when we aren't
|
||||
@ -1192,7 +1180,7 @@ void SkScalerContext_Mac::generateImage(const SkGlyph& glyph) {
|
||||
int r = (addr[x] >> 16) & 0xFF;
|
||||
int g = (addr[x] >> 8) & 0xFF;
|
||||
int b = (addr[x] >> 0) & 0xFF;
|
||||
addr[x] = (table[r] << 16) | (table[g] << 8) | table[b];
|
||||
addr[x] = (linear[r] << 16) | (linear[g] << 8) | linear[b];
|
||||
}
|
||||
addr = SkTAddOffset<CGRGBPixel>(addr, cgRowBytes);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user