#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using pii = pair<int, int>;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
template <class Ty>
Ty randint(Ty a, Ty b) {
  return uniform_int_distribution<Ty>(a, b)(rng);
}
template <class T>
void DBG(T&& x) {
  cerr << x << " ";
}
template <class T, class... Args>
void DBG(T&& x, Args&&... args) {
  DBG(x);
  DBG(args...);
}
template <class num>
inline void rd(istream& in, num& x) {
  in >> x;
}
template <class Ty, class... Args>
inline void rd(istream& in, Ty& x, Args&... args) {
  rd(in, x);
  rd(in, args...);
}
template <class num>
inline void print(ostream& out, num&& x) {
  out << x;
}
template <class Ty, class... Args>
inline void print(std::ostream& out, Ty&& x, Args&&... args) {
  print(out, x);
  print(out, ' ');
  print(out, args...);
}
template <const int MOD>
struct Mint {
  int v;
  Mint() : v{} {}
  Mint(int v) : v(v) { go(); }
  inline void go() {
    if (abs(v) >= MOD) v %= MOD;
    if (v < 0) v += MOD;
  }
  inline static Mint fpow(Mint x, long long y) {
    Mint r = 1;
    for (; y > 0; y /= 2, x *= x)
      if (y % 2 != 0) r *= x;
    return r;
  }
  Mint inv() const { return fpow(*this, MOD - 2); }
  Mint operator+(Mint const& m) const {
    return v + m.v >= MOD ? v + m.v - MOD : v + m.v;
  }
  Mint operator-(Mint const& m) const {
    return v - m.v < 0 ? v - m.v + MOD : v - m.v;
  }
  Mint operator*(Mint const& m) const { return (long long)v * m.v % MOD; }
  Mint operator/(Mint const& m) const { return (*this) * m.inv(); }
  Mint operator^(long long m) const { return fpow(*this, m); }
  Mint& operator+=(Mint const& m) { return (*this) = (*this) + m; }
  Mint& operator-=(Mint const& m) { return (*this) = (*this) - m; }
  Mint& operator*=(Mint const& m) { return (*this) = (*this) * m; }
  Mint& operator/=(Mint const& m) { return (*this) = (*this) / m; }
};
const int MOD = 1e9 + 7;
using mint = Mint<MOD>;
inline bool is_set(int mask, int pos) { return mask & (1 << pos); }
inline int flip(int mask, int pos) { return mask ^ (1 << pos); }
inline int setm(int mask, int pos) { return mask | (1 << pos); }
inline int reset(int mask, int pos) { return mask & (~(1 << pos)); }
class BGuardsInTheStorehouse {
 public:
  void solve(std::istream& in, std::ostream& out) {
    int n, m;
    rd(in, n, m);
    vector<string> a(n);
    for (auto& i : a) rd(in, i);
    if (n < m) {
      vector<string> b(m, string(n, '?'));
      for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++) {
          b[j][i] = a[i][j];
        }
      swap(n, m);
      swap(a, b);
    }
    vector<vector<vector<mint>>> old(
        1 << m, vector<vector<mint>>(2, vector<mint>(2, mint(1))));
    vector<vector<vector<mint>>> cur(
        1 << m, vector<vector<mint>>(2, vector<mint>(2, mint(1))));
    for (int pos = n * m - 1; pos >= 0; pos--) {
      swap(old, cur);
      int row = pos / m;
      int col = pos % m;
      for (int mask = 0; mask < (1 << m); mask++) {
        for (int ignored = 0; ignored <= 1; ignored++) {
          for (int used_row = 0; used_row <= 1; used_row++) {
            mint& ret = cur[mask][ignored][used_row];
            if (a[row][col] == 'x') {
              ret = old[reset(mask, col)][ignored][0];
            } else {
              if (col == m - 1) {
                ret = old[setm(mask, col)][ignored][0];
                int nignored = ignored + !(is_set(mask, col) || used_row);
                if (nignored <= 1) ret += old[mask][nignored][0];
              } else {
                ret = old[setm(mask, col)][ignored][1];
                int nignored = ignored + !(is_set(mask, col) || used_row);
                if (nignored <= 1) ret += old[mask][nignored][used_row];
              }
            }
          }
        }
      }
    }
    print(out, cur[0][0][0].v), print(out, '\n');
  }
};
int main() {
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  BGuardsInTheStorehouse solver;
  std::istream& in(std::cin);
  std::ostream& out(std::cout);
  solver.solve(in, out);
  return 0;
}
