// #define LOCAL
#define _USE_MATH_DEFINES
#include <array>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <list>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <algorithm>
#include <complex>
#include <cmath>
#include <numeric>
#include <bitset>
#include <functional>
#include <random>
#include <ctime>

using namespace std;

template <typename A, typename B>
ostream& operator <<(ostream& out, const pair<A, B>& a) {
  out << "(" << a.first << "," << a.second << ")";
  return out;
}
template <typename T, size_t N>
ostream& operator <<(ostream& out, const array<T, N>& a) {
  out << "["; bool first = true;
  for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]";
  return out;
}
template <typename T>
ostream& operator <<(ostream& out, const vector<T>& a) {
  out << "["; bool first = true;
  for (auto v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "]";
  return out;
}
template <typename T, class Cmp>
ostream& operator <<(ostream& out, const set<T, Cmp>& a) {
  out << "{"; bool first = true;
  for (auto& v : a) { out << (first ? "" : ", "); out << v; first = 0;} out << "}";
  return out;
}
template <typename U, typename T, class Cmp>
ostream& operator <<(ostream& out, const map<U, T, Cmp>& a) {
  out << "{"; bool first = true;
  for (auto& p : a) { out << (first ? "" : ", "); out << p.first << ":" << p.second; first = 0;} out << "}";
  return out;
}
#ifdef LOCAL
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
#else
#define trace(...) 42
#endif
template <typename Arg1>
void __f(const char* name, Arg1&& arg1){
  cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&&... args){
  const char* comma = strchr(names + 1, ',');
  cerr.write(names, comma - names) << ": " << arg1 << " |";
  __f(comma + 1, args...);
}

typedef long long int64;
typedef pair<int, int> ii;
#define SZ(x) (int)((x).size())
template <typename T> static constexpr T inf = numeric_limits<T>::max() / 2;
const int MOD = 1e9 + 7;
mt19937 mrand(random_device{}());
int rnd(int x) { return mrand() % x; }

struct fast_ios {
  fast_ios() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(10);
  };
} fast_ios_;

void add(int& x, int y) {
  x += y;
  if (x >= MOD) x -= MOD;
}

int main() {
  int n, m;
  cin >> n >> m;
  vector<string> s(n);
  for (int i = 0; i < n; ++i) cin >> s[i];
  vector<vector<int>> L(n, vector<int>(m));
  vector<vector<int>> R(n, vector<int>(m));
  vector<vector<int>> U(n, vector<int>(m));
  vector<vector<int>> D(n, vector<int>(m));
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      if (s[i][j] == '#') continue;
      L[i][j] = j - 1 >= 0 ? L[i][j - 1] + 1 : 1;
    }
    for (int j = m - 1; j >= 0; --j) {
      if (s[i][j] == '#') continue;
      R[i][j] = j + 1 < m ? R[i][j + 1] + 1 : 1;
    }
  }
  for (int j = 0; j < m; ++j) {
    for (int i = 0; i < n; ++i) {
      if (s[i][j] == '#') continue;
      U[i][j] = i - 1 >= 0 ? U[i - 1][j] + 1 : 1;
    }
    for (int i = n - 1; i >= 0; --i) {
      if (s[i][j] == '#') continue;
      D[i][j] = i + 1 < n ? D[i + 1][j] + 1 : 1;
    }
  }
  int sum = 0;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) sum += s[i][j] == '.';
  }
  vector<int> p2(n * m + 1);
  p2[0] = 1;
  for (int i = 1; i <= n * m; ++i) p2[i] = p2[i - 1] * 2LL % MOD;
  int ret = 0;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < m; ++j) {
      if (s[i][j] == '#') continue;
      int cnt = L[i][j] + R[i][j] + U[i][j] + D[i][j] - 3;
      trace(i, j, sum, cnt);
      int cur = p2[sum] - p2[sum - cnt];
      if (cur < 0) cur += MOD;
      add(ret, cur);
    }
  }
  cout << ret << '\n';
  return 0;
}

#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cinttypes>
#include<vector>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<string>
#include<stack>


#define FSCNd64 "%" SCNd64
#define FPRId64 "%" PRId64

using namespace std;

using ll=long long;
using vi=vector<int>;
using vvi=vector<vi>;
using pii=pair<int,int>;
using vll=vector<ll>;
using vvll=vector<vll>;
using vpii=vector<pii>;

#define PI 3.1415926535897932384626433832795

template<typename X>
bool max_u(X&m, X v)
{
	if(m<v)
	{
		m=v;
		return true;
	}
	return false;
}


template<typename X>
bool min_u(X&m, X v)
{
	if(m>v)
	{
		m=v;
		return true;
	}
	return false;
}


using ll=long long;

class mod_ll
{
public:
	ll m_v;
	static const ll m_m=1000000007; // prime value ex. 1000000009
	mod_ll(ll v=0) : m_v(v%m_m) {}
	mod_ll& operator = (ll rhs)
	{
		m_v=rhs%m_m;
		return *this;
	}
	ll operator ()(){return (m_v+m_m)%m_m;}
	mod_ll& operator += (const mod_ll rhs)
	{
		m_v=(m_v+rhs.m_v)%m_m;
		return *this;
	}
	const mod_ll operator + (const mod_ll rhs)
	{
		auto ret=*this;
		return ret+=rhs;
	}
	mod_ll& operator -= (const mod_ll rhs)
	{
		m_v=(m_v-rhs.m_v+m_m)%m_m;
		return *this;
	}
	const mod_ll operator - (const mod_ll rhs)
	{
		auto ret=*this;
		return ret-=rhs;
	}
	mod_ll& operator *= (const mod_ll rhs)
	{
		m_v=(m_v*rhs.m_v)%m_m;
		return *this;
	}
	const mod_ll operator * (const mod_ll rhs)
	{
		mod_ll ret=*this;
		return ret*=rhs;
	}
	const mod_ll operator ^ (ll rhs)
	{
		mod_ll t=*this;
		mod_ll ret(1LL);

		for(;rhs>0;rhs>>=1)
		{
			if(rhs&1) ret*=t;
			t*=t;
		}
		return ret;
	}
	mod_ll& operator /= (mod_ll rhs)
	{
		mod_ll t=rhs^(m_m-2);
		return *this*=t;
	}
	const mod_ll operator / (const mod_ll rhs)
	{
		mod_ll ret=*this;
		return ret/=rhs;
	}
};


mod_ll mod_fact(int n)
{
	static vector<mod_ll> memo(1);

	if((int)memo.size()<=n)
	{
		if(memo.size()==1)
		{
			memo[0]=1;
		}
		for(int i=memo.size();i<=n;i++)
		{
			memo.push_back(memo.back()*i);
		}
	}
	return memo[n];
}


mod_ll mod_nCr(int n, int r)
{
	if(n<=0) return 1;
	return mod_fact(n)/(mod_fact(n-r)*mod_fact(r));
}


mod_ll mod_nCr2(int n, int r)
{
	mod_ll bunsi(1);
	mod_ll bunbo(1);
	if(r*2>n) r=n-r;

	for(int i=0;i<r;i++)
	{
		bunsi*=(n-i);
		bunbo*=(i+1);
	}
	return bunsi/bunbo;
}


mod_ll mod_nPr(int n, int r)
{
	return mod_fact(n)/mod_fact(n-r);
}


struct solve
{
	solve(){}
	ll operator()(vector<string>&s) {
		int h=s.size();
		int w=s[0].length();
		vvi cx(h), cy(h);

		for(auto&m:cx) m.assign(w, -1);
		for(auto&m:cy) m.assign(w, -1);

		int n=0;
		for(int y=0;y<h;y++)
		{
			for(int x=0;x<w;x++)
			{
				if(s[y][x]!='.') continue;
				cx[y][x]=(x>0)?max(cx[y][x-1]+1, 1):1;
				cy[y][x]=(y>0)?max(cy[y-1][x]+1, 1):1;
				n++;
			}
		}

		vector<mod_ll> beki2(n+1);
		beki2[0]=1;
		for(int i=1;i<=n;i++) beki2[i]=beki2[i-1]*2;

		for(int y=h-1;y>=0;y--)
		{
			int v=cx[y][w-1];
			for(int x=w-1;x>=0;x--)
			{
				max_u(v, cx[y][x]);
				if(cx[y][x]>0) cx[y][x]=v;
				else v=-1;
			}
		}

		for(int x=w-1;x>=0;x--)
		{
			int v=-1;
			for(int y=h-1;y>=0;y--)
			{
				max_u(v, cy[y][x]);
				if(cy[y][x]>0) cy[y][x]=v;
				else v=-1;
			}
		}

		mod_ll t=0;
		for(int y=0;y<h;y++)
		{
			for(int x=0;x<w;x++)
			{
				int v=cx[y][x]+cy[y][x]-1;
				if(v>0) t+=beki2[n-v];
			}
		}

		mod_ll ans=(beki2[n]*n);
		ans-=t;
/*
		cout << beki2[n]() << "\n";
		cout << t() << "\n";
*/
		return ans();
	}
};

int main(void)
{
	ios::sync_with_stdio(false);
	cin.tie(nullptr);

	for(;;)
	{
		int h, w;
		cin >> h >> w;
		if(cin.fail()) break;
		vector<string> s(h);
		for(auto&m:s) cin >> m;

		cout << solve()(s) << "\n";
	}
	return 0;
}
