diff --git a/docs/reference/gtk/meson.build b/docs/reference/gtk/meson.build index b643adf676..8bac03063a 100644 --- a/docs/reference/gtk/meson.build +++ b/docs/reference/gtk/meson.build @@ -169,6 +169,7 @@ private_headers = [ 'gtkplacesviewprivate.h', 'gtkplacesviewrowprivate.h', 'gtkpointerfocusprivate.h', + 'gtkpopcountprivate.h', 'gtkpopoverprivate.h', 'gtkprinterprivate.h', 'gtkprintoperation-private.h', diff --git a/gtk/gtkcssenumvalue.c b/gtk/gtkcssenumvalue.c index 82d5580773..9bd29e3742 100644 --- a/gtk/gtkcssenumvalue.c +++ b/gtk/gtkcssenumvalue.c @@ -24,9 +24,7 @@ #include "gtkstyleproviderprivate.h" #include "gtksettingsprivate.h" -#ifdef _MSC_VER -# include -#endif +#include "gtkpopcountprivate.h" /* repeated API */ @@ -1453,39 +1451,6 @@ static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT_EAST_ASIAN = { gtk_css_font_variant_east_asian_value_print }; -#ifdef _MSC_VER -/* __builtin_popcount is a GCC-only function - so we need to define it for ourselves somehow */ - -static inline guint -__msvc_compat_popcnt (guint32 value) -{ - static gssize popcnt_checked = 0; - static gboolean have_popcnt = FALSE; - -# if defined (_M_AMD64) || defined (_M_X64) || (_M_IX86) - if (g_once_init_enter (&popcnt_checked)) - { - int cpuinfo[4] = {-1}; - - __cpuid (cpuinfo, 1); - have_popcnt = (cpuinfo[2] & 0x00800000) != 0; - g_once_init_leave (&popcnt_checked, 1); - } -# endif - - if (have_popcnt) - return __popcnt (value); - else - /* http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel */ - return (((value & 0xfff) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f) + - ((((value & 0xfff000) >> 12) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f) + - (((value >> 24) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f); -} - -# define __builtin_popcount(v) __msvc_compat_popcnt(v) -#endif - static gboolean east_asian_value_is_valid (GtkCssFontVariantEastAsian east_asian) { @@ -1493,16 +1458,16 @@ east_asian_value_is_valid (GtkCssFontVariantEastAsian east_asian) (east_asian != GTK_CSS_FONT_VARIANT_EAST_ASIAN_NORMAL)) return FALSE; - if (__builtin_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS78 | - GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS83 | - GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS90 | - GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS04 | - GTK_CSS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED | - GTK_CSS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL)) > 1) + if (gtk_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS78 | + GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS83 | + GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS90 | + GTK_CSS_FONT_VARIANT_EAST_ASIAN_JIS04 | + GTK_CSS_FONT_VARIANT_EAST_ASIAN_SIMPLIFIED | + GTK_CSS_FONT_VARIANT_EAST_ASIAN_TRADITIONAL)) > 1) return FALSE; - if (__builtin_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH | - GTK_CSS_FONT_VARIANT_EAST_ASIAN_PROPORTIONAL)) > 1) + if (gtk_popcount (east_asian & (GTK_CSS_FONT_VARIANT_EAST_ASIAN_FULL_WIDTH | + GTK_CSS_FONT_VARIANT_EAST_ASIAN_PROPORTIONAL)) > 1) return FALSE; return TRUE; diff --git a/gtk/gtkmain.c b/gtk/gtkmain.c index 13aa3dd10e..60e4a7b580 100644 --- a/gtk/gtkmain.c +++ b/gtk/gtkmain.c @@ -132,6 +132,7 @@ #include "gtkimmodule.h" #include "gtkroot.h" #include "gtknative.h" +#include "gtkpopcountprivate.h" #include "inspector/window.h" @@ -1484,9 +1485,11 @@ handle_pointing_event (GdkEvent *event) modifiers = gdk_event_get_modifier_state (event); if (type == GDK_BUTTON_RELEASE && - __builtin_popcount (modifiers & - (GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK | - GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)) == 1) + gtk_popcount (modifiers & (GDK_BUTTON1_MASK | + GDK_BUTTON2_MASK | + GDK_BUTTON3_MASK | + GDK_BUTTON4_MASK | + GDK_BUTTON5_MASK)) == 1) { GtkWidget *new_target = gtk_widget_pick (native, x, y, GTK_PICK_DEFAULT); diff --git a/gtk/gtkpopcountprivate.h b/gtk/gtkpopcountprivate.h new file mode 100644 index 0000000000..8a99dd2b26 --- /dev/null +++ b/gtk/gtkpopcountprivate.h @@ -0,0 +1,42 @@ +/* gtkpopcountprivate.h: Private implementation of popcount + * + * Copyright 2020 GNOME Foundation + * + * SPDX-License-Identifier: LGPL-2.1-or-later + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * 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, see . + */ + +#pragma once + +#if defined(_MSC_VER) +#include + +static inline guint +gtk_popcount (guint32 value) +{ + return __popcnt (value); +} +#elif defined(__GNUC__) || defined(__clang__) +# define gtk_popcount(v) __builtin_popcount(v) +#else +static inline guint +gtk_popcount (guint32 value) +{ + /* http://graphics.stanford.edu/~seander/bithacks.html#CountBitsSetParallel */ + return (((value & 0xfff) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f) + + ((((value & 0xfff000) >> 12) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f) + + (((value >> 24) * 0x1001001001001ULL & 0x84210842108421ULL) % 0x1f); +} +#endif