First, we want to find the locations where the array has a zero next to a non-zero.
rr, cc = np.where((arr[:, 1:] == 0) & (arr[:, :-1] != 0))
Now, we can use np.add.reduceat to add elements. Unfortunately, reduceat needs a list of 1-d indices, so we're going to have to play with shapes a little. Calculating the equivalent indices of rr, cc in a flattened array is easy:
reduce_indices = rr * arr.shape[1] + cc + 1
# array([ 4,  8, 10, 13, 19, 26, 28])
We want to reduce from the start of every row, so we'll create a row_starts to mix in with the indices calculated above:
row_starts = np.arange(arr.shape[0]) * arr.shape[1]
# array([ 0, 11, 22])
reduce_indices = np.hstack((row_starts, reduce_indices))
reduce_indices.sort()
# array([ 0,  4,  8, 10, 11, 13, 19, 22, 26, 28])
Now, call np.add.reduceat on the flattened input array, reducing at reduce_indices
totals = np.add.reduceat(arr.flatten(), reduce_indices)
# array([ 7,  9,  3,  0,  3, 12,  0, 25,  1,  1])
Now we have the totals, we need to assign them to an array of zeros. Note that the 0th element of totals needs to go to the 1th index of reduce_indices, and the last element of totals is to be discarded:
result_f = np.zeros((arr.size,))
result_f[reduce_indices[1:]] = totals[:-1]
result = result_f.reshape(arr.shape)
Now, one last step remains. For cases where the last element in a row is nonzero, reduceat would calculate a nonzero value for the first element of the next row, as you mentioned in the comment below. An easy solution is to overwrite these to zero.
result[:, 0] = 0
which gives the expected result:
array([[ 0.,  0.,  0.,  0.,  7.,  0.,  0.,  0.,  9.,  0.,  3.],
       [ 0.,  0.,  3.,  0.,  0.,  0.,  0.,  0., 12.,  0.,  0.],
       [ 0.,  0.,  0.,  0., 25.,  0.,  1.,  0.,  0.,  0.,  0.]])