Repository: Qiskit/qiskit

Issue:
Drawing initialize disordered in mpl drawer
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

- **Qiskit Terra version**: 0.12.0.dev0+6b6170a
- **Python version**: 3.6
- **Operating system**: Ubuntu 18.04

### What is the current behavior?
The box of 'initialize' is disordered. It gets outside of the circuit and overlaps with other gates.

![initialize-error](https://user-images.githubusercontent.com/51048173/71252473-1f210b00-234b-11ea-9746-6933f0acf3c7.png)


### Steps to reproduce the problem

```from qiskit import *
from math import pi, sqrt
import numpy as np

vec = np.array([sqrt(1/2), 0, 0, sqrt(1/2)])

qc = QuantumCircuit(2)
qc.initialize(vec, [0,1])
qc.u3(0.12,pi/2,pi/4,0)
qc.draw(output="mpl")
```

### What is the expected behavior?



### Suggested solutions



Circuit marplot lib register and measurement on-top of each other
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues to confirm this idea does not exist. -->

### What is the expected enhancement?
If the circuit goes over two frames the second frame if it is a measurement the register and the value are on top of each other -- see figure. 

![image](https://user-images.githubusercontent.com/15731369/79181843-58d6bf80-7ddb-11ea-934e-9f4cea88aaa2.png)




Discussion:
I'd like to give a shot at this, would that be okay to you?
Hi @NuoWenLei . Yeah sure. That would be very nice.
Ok, thank you. Would you mind assigning the issue to me?
I was able to locate the problem within mathplotlib.py`
  # if custom gate with a longer than standard name determine
                # width
                elif op.name not in ['barrier', 'snapshot', 'load', 'save',
                                     'noise', 'cswap', 'swap', 'measure'] and len(
                                         op.name) >= 4:
                    box_width = math.ceil(len(op.name) / 6)
                    # handle params/subtext longer than op names
                    if op.type == 'op' and hasattr(op.op, 'params'):
                        param = self.param_parse(op.op.params)
                        if '$\\pi$' in param:
                            pi_count = param.count('pi')
                            len_param = len(param) - (4 * pi_count)
                        else:
                            len_param = len(param)
                        if len_param > len(op.name):
                            box_width = math.floor(len(param) / 8)
                            # If more than 4 characters min width is 2
                            if box_width <= 1:
                                box_width = 2
                            if layer_width < box_width:
                                if box_width > 2:
                                    layer_width = box_width * 2
                                else:
                                    layer_width = 2
                            continue
`, so I changed `box_width = math.floor(len(param) / 8)` to `box_width = math.ceil(len(param) / 8)`

This is the result:
![Screen Shot 2019-12-23 at 8 10 11 PM](https://user-images.githubusercontent.com/46566976/71357321-45031580-25c0-11ea-9f74-5b3bfcfcd8ed.png)

Only uncertainty is the other custom multiqubit quantum gates, such as unitary.

That looks good. But, if possible, check if the width of the 'initialize' box can be reduced so as to eliminate the extra spaces inside the box. As for the other gates, it would be good to check that the change does not affect other gates for the worse.
Cool
Not sure if this falls under the same issue, but the circuit created by `.gates_to_uncompute()` also has drawing problems:

```
init_gate = Initialize([1,0])
inverse_init_gate = init_gate.gates_to_uncompute()
qc.append(inverse_init_gate, [2])
qc.draw('mpl')
```

<img width="375" alt="Screenshot 2020-03-28 at 09 25 40" src="https://user-images.githubusercontent.com/36071638/77819888-46b80a00-70d6-11ea-9365-8b9972db2807.png">


Resolving patch:
diff --git a/qiskit/visualization/circuit_visualization.py b/qiskit/visualization/circuit_visualization.py
--- a/qiskit/visualization/circuit_visualization.py
+++ b/qiskit/visualization/circuit_visualization.py
@@ -129,10 +129,9 @@ def circuit_drawer(circuit,
             when the ``output`` kwarg is set to use the ``mpl`` backend. It
             will be silently ignored with all other outputs.
         initial_state (bool): Optional. Adds ``|0>`` in the beginning of the wire.
-            Only used by the ``text``, ``latex`` and ``latex_source`` outputs.
             Default: ``False``.
-        cregbundle (bool): Optional. If set True bundle classical registers. Not used by
-            the ``matplotlib`` output. Default: ``False``.
+        cregbundle (bool): Optional. If set True bundle classical registers.
+            Default: ``False``.
 
     Returns:
         :class:`PIL.Image` or :class:`matplotlib.figure` or :class:`str` or
@@ -314,7 +313,9 @@ def circuit_drawer(circuit,
                                            idle_wires=idle_wires,
                                            with_layout=with_layout,
                                            fold=fold,
-                                           ax=ax)
+                                           ax=ax,
+                                           initial_state=initial_state,
+                                           cregbundle=cregbundle)
     else:
         raise exceptions.VisualizationError(
             'Invalid output type %s selected. The only valid choices '
@@ -613,7 +614,10 @@ def _matplotlib_circuit_drawer(circuit,
                                idle_wires=True,
                                with_layout=True,
                                fold=None,
-                               ax=None):
+                               ax=None,
+                               initial_state=False,
+                               cregbundle=True):
+
     """Draw a quantum circuit based on matplotlib.
     If `%matplotlib inline` is invoked in a Jupyter notebook, it visualizes a circuit inline.
     We recommend `%config InlineBackend.figure_format = 'svg'` for the inline visualization.
@@ -637,6 +641,10 @@ def _matplotlib_circuit_drawer(circuit,
             the visualization output. If none is specified a new matplotlib
             Figure will be created and used. Additionally, if specified there
             will be no returned Figure since it is redundant.
+        initial_state (bool): Optional. Adds |0> in the beginning of the line.
+            Default: `False`.
+        cregbundle (bool): Optional. If set True bundle classical registers.
+            Default: ``True``.
 
     Returns:
         matplotlib.figure: a matplotlib figure object for the circuit diagram
@@ -658,5 +666,6 @@ def _matplotlib_circuit_drawer(circuit,
     qcd = _matplotlib.MatplotlibDrawer(qregs, cregs, ops, scale=scale, style=style,
                                        plot_barriers=plot_barriers,
                                        reverse_bits=reverse_bits, layout=layout,
-                                       fold=fold, ax=ax)
+                                       fold=fold, ax=ax, initial_state=initial_state,
+                                       cregbundle=cregbundle)
     return qcd.draw(filename)
diff --git a/qiskit/visualization/matplotlib.py b/qiskit/visualization/matplotlib.py
--- a/qiskit/visualization/matplotlib.py
+++ b/qiskit/visualization/matplotlib.py
@@ -17,12 +17,10 @@
 """mpl circuit visualization backend."""
 
 import collections
-import fractions
 import itertools
 import json
 import logging
-import math
-
+from warnings import warn
 import numpy as np
 
 try:
@@ -35,15 +33,17 @@
     HAS_MATPLOTLIB = False
 
 from qiskit.circuit import ControlledGate
-from qiskit.visualization import exceptions
 from qiskit.visualization.qcstyle import DefaultStyle, BWStyle
 from qiskit import user_config
 from qiskit.circuit.tools.pi_check import pi_check
 
 logger = logging.getLogger(__name__)
 
+# Default gate width and height
 WID = 0.65
 HIG = 0.65
+
+DEFAULT_SCALE = 4.3
 PORDER_GATE = 5
 PORDER_LINE = 3
 PORDER_REGLINE = 2
@@ -84,11 +84,14 @@ def is_locatable(self, index, gate_width):
         return True
 
     def set_index(self, index, gate_width):
-        h_pos = index % self.__fold + 1
-        if h_pos + (gate_width - 1) > self.__fold:
-            _index = index + self.__fold - (h_pos - 1)
-        else:
+        if self.__fold < 2:
             _index = index
+        else:
+            h_pos = index % self.__fold + 1
+            if h_pos + (gate_width - 1) > self.__fold:
+                _index = index + self.__fold - (h_pos - 1) + 1
+            else:
+                _index = index
         for ii in range(gate_width):
             if _index + ii not in self.__gate_placed:
                 self.__gate_placed.append(_index + ii)
@@ -103,14 +106,15 @@ def get_index(self):
 class MatplotlibDrawer:
     def __init__(self, qregs, cregs, ops,
                  scale=1.0, style=None, plot_barriers=True,
-                 reverse_bits=False, layout=None, fold=25, ax=None):
+                 reverse_bits=False, layout=None, fold=25, ax=None,
+                 initial_state=False, cregbundle=True):
 
         if not HAS_MATPLOTLIB:
             raise ImportError('The class MatplotlibDrawer needs matplotlib. '
                               'To install, run "pip install matplotlib".')
 
         self._ast = None
-        self._scale = scale
+        self._scale = DEFAULT_SCALE * scale
         self._creg = []
         self._qreg = []
         self._registers(cregs, qregs)
@@ -138,6 +142,16 @@ def __init__(self, qregs, cregs, ops,
         self.plot_barriers = plot_barriers
         self.reverse_bits = reverse_bits
         self.layout = layout
+        self.initial_state = initial_state
+        if style and 'cregbundle' in style.keys():
+            self.cregbundle = style['cregbundle']
+            del style['cregbundle']
+            warn("The style dictionary key 'cregbundle' has been deprecated and will be removed"
+                 " in a future release. cregbundle is now a parameter to draw()."
+                 " Example: circuit.draw(output='mpl', cregbundle=False)", DeprecationWarning, 2)
+        else:
+            self.cregbundle = cregbundle
+
         if style:
             if isinstance(style, dict):
                 self._style.set_style(style)
@@ -145,6 +159,7 @@ def __init__(self, qregs, cregs, ops,
                 with open(style, 'r') as infile:
                     dic = json.load(infile)
                 self._style.set_style(dic)
+
         if ax is None:
             self.return_fig = True
             self.figure = plt.figure()
@@ -155,6 +170,18 @@ def __init__(self, qregs, cregs, ops,
             self.ax = ax
             self.figure = ax.get_figure()
 
+        self.x_offset = 0
+        self._reg_long_text = 0
+
+        # default is to use character table for text width,
+        # but get_renderer will work with some mpl backends
+        """fig = plt.figure()
+        if hasattr(fig.canvas, 'get_renderer'):
+            self.renderer = fig.canvas.get_renderer()
+        else:
+            self.renderer = None"""
+        self.renderer = None
+
         self.fold = fold
         if self.fold < 2:
             self.fold = -1
@@ -164,7 +191,43 @@ def __init__(self, qregs, cregs, ops,
         self.ax.tick_params(labelbottom=False, labeltop=False,
                             labelleft=False, labelright=False)
 
-        self.x_offset = 0
+        # these char arrays are for finding text_width when not
+        # using get_renderer method for the matplotlib backend
+        self._latex_chars = ('$', '{', '}', '_', '\\left', '\\right',
+                             '\\dagger', '\\rangle')
+        self._latex_chars1 = ('\\mapsto', '\\pi', '\\;')
+        self._char_list = {' ': (0.0958, 0.0583), '!': (0.1208, 0.0729), '"': (0.1396, 0.0875),
+                           '#': (0.2521, 0.1562), '$': (0.1917, 0.1167), '%': (0.2854, 0.1771),
+                           '&': (0.2333, 0.1458), "'": (0.0833, 0.0521), '(': (0.1167, 0.0729),
+                           ')': (0.1167, 0.0729), '*': (0.15, 0.0938), '+': (0.25, 0.1562),
+                           ',': (0.0958, 0.0583), '-': (0.1083, 0.0667), '.': (0.0958, 0.0604),
+                           '/': (0.1021, 0.0625), '0': (0.1875, 0.1167), '1': (0.1896, 0.1167),
+                           '2': (0.1917, 0.1188), '3': (0.1917, 0.1167), '4': (0.1917, 0.1188),
+                           '5': (0.1917, 0.1167), '6': (0.1896, 0.1167), '7': (0.1917, 0.1188),
+                           '8': (0.1896, 0.1188), '9': (0.1917, 0.1188), ':': (0.1021, 0.0604),
+                           ';': (0.1021, 0.0604), '<': (0.25, 0.1542), '=': (0.25, 0.1562),
+                           '>': (0.25, 0.1542), '?': (0.1583, 0.0979), '@': (0.2979, 0.1854),
+                           'A': (0.2062, 0.1271), 'B': (0.2042, 0.1271), 'C': (0.2083, 0.1292),
+                           'D': (0.2312, 0.1417), 'E': (0.1875, 0.1167), 'F': (0.1708, 0.1062),
+                           'G': (0.2312, 0.1438), 'H': (0.225, 0.1396), 'I': (0.0875, 0.0542),
+                           'J': (0.0875, 0.0542), 'K': (0.1958, 0.1208), 'L': (0.1667, 0.1042),
+                           'M': (0.2583, 0.1604), 'N': (0.225, 0.1396), 'O': (0.2354, 0.1458),
+                           'P': (0.1812, 0.1125), 'Q': (0.2354, 0.1458), 'R': (0.2083, 0.1292),
+                           'S': (0.1896, 0.1188), 'T': (0.1854, 0.1125), 'U': (0.2208, 0.1354),
+                           'V': (0.2062, 0.1271), 'W': (0.2958, 0.1833), 'X': (0.2062, 0.1271),
+                           'Y': (0.1833, 0.1125), 'Z': (0.2042, 0.1271), '[': (0.1167, 0.075),
+                           '\\': (0.1021, 0.0625), ']': (0.1167, 0.0729), '^': (0.2521, 0.1562),
+                           '_': (0.1521, 0.0938), '`': (0.15, 0.0938), 'a': (0.1854, 0.1146),
+                           'b': (0.1917, 0.1167), 'c': (0.1646, 0.1021), 'd': (0.1896, 0.1188),
+                           'e': (0.1854, 0.1146), 'f': (0.1042, 0.0667), 'g': (0.1896, 0.1188),
+                           'h': (0.1896, 0.1188), 'i': (0.0854, 0.0521), 'j': (0.0854, 0.0521),
+                           'k': (0.1729, 0.1083), 'l': (0.0854, 0.0521), 'm': (0.2917, 0.1812),
+                           'n': (0.1896, 0.1188), 'o': (0.1833, 0.1125), 'p': (0.1917, 0.1167),
+                           'q': (0.1896, 0.1188), 'r': (0.125, 0.0771), 's': (0.1562, 0.0958),
+                           't': (0.1167, 0.0729), 'u': (0.1896, 0.1188), 'v': (0.1771, 0.1104),
+                           'w': (0.2458, 0.1521), 'x': (0.1771, 0.1104), 'y': (0.1771, 0.1104),
+                           'z': (0.1562, 0.0979), '{': (0.1917, 0.1188), '|': (0.1, 0.0604),
+                           '}': (0.1896, 0.1188)}
 
     def _registers(self, creg, qreg):
         self._creg = []
@@ -178,295 +241,282 @@ def _registers(self, creg, qreg):
     def ast(self):
         return self._ast
 
-    def _custom_multiqubit_gate(self, xy, cxy=None, fc=None, wide=True, text=None,
-                                subtext=None):
-        xpos = min([x[0] for x in xy])
-        ypos = min([y[1] for y in xy])
-        ypos_max = max([y[1] for y in xy])
+    # This computes the width of a string in the default font
+    def _get_text_width(self, text, fontsize):
+        if not text:
+            return 0.0
 
-        if cxy:
-            ypos = min([y[1] for y in cxy])
-        if wide:
-            if subtext:
-                boxes_length = round(max([len(text), len(subtext)]) / 7) or 1
-            else:
-                boxes_length = math.ceil(len(text) / 7) or 1
-            wid = WID * 2.5 * boxes_length
+        if self.renderer:
+            t = plt.text(0.5, 0.5, text, fontsize=fontsize)
+            return t.get_window_extent(renderer=self.renderer).width / 60.0
         else:
-            wid = WID
+            # if not using a get_renderer method, first remove
+            # any latex chars before getting width
+            for t in self._latex_chars1:
+                text = text.replace(t, 'r')
+            for t in self._latex_chars:
+                text = text.replace(t, '')
+
+            f = 0 if fontsize == self._style.fs else 1
+            sum_text = 0.0
+            for c in text:
+                try:
+                    sum_text += self._char_list[c][f]
+                except KeyError:
+                    # if non-ASCII char, use width of 'r', an average size
+                    sum_text += self._char_list['r'][f]
+            return sum_text
+
+    def param_parse(self, v):
+        # create an empty list to store the parameters in
+        param_parts = [None] * len(v)
+        for i, e in enumerate(v):
+            try:
+                param_parts[i] = pi_check(e, output='mpl', ndigits=3)
+            except TypeError:
+                param_parts[i] = str(e)
 
-        if fc:
-            _fc = fc
+            if param_parts[i].startswith('-'):
+                param_parts[i] = '$-$' + param_parts[i][1:]
+
+        param_parts = ', '.join(param_parts)
+        # remove $'s since "${}$".format will add them back on the outside
+        param_parts = param_parts.replace('$', '')
+        param_parts = param_parts.replace('-', u'\u02d7')
+        return param_parts
+
+    def _get_gate_ctrl_text(self, op):
+        op_label = getattr(op.op, 'label', None)
+        base_name = None if not hasattr(op.op, 'base_gate') else op.op.base_gate.name
+        base_label = None if not hasattr(op.op, 'base_gate') else op.op.base_gate.label
+        ctrl_text = None
+        if base_label:
+            gate_text = base_label
+            ctrl_text = op_label
+        elif op_label and isinstance(op.op, ControlledGate):
+            gate_text = base_name
+            ctrl_text = op_label
+        elif op_label:
+            gate_text = op_label
+        elif base_name:
+            gate_text = base_name
         else:
-            if self._style.name != 'bw':
-                if self._style.gc != DefaultStyle().gc:
-                    _fc = self._style.gc
-                else:
-                    _fc = self._style.dispcol['multi']
-                _ec = self._style.dispcol['multi']
-            else:
-                _fc = self._style.gc
+            gate_text = op.name
+
+        if gate_text in self._style.disptex:
+            gate_text = "${}$".format(self._style.disptex[gate_text])
+        else:
+            gate_text = "${}$".format(gate_text[0].upper() + gate_text[1:])
+
+        # mathtext .format removes spaces so add them back and it changes
+        # hyphen to wide minus sign, so use unicode hyphen to prevent that
+        gate_text = gate_text.replace(' ', '\\;')
+        gate_text = gate_text.replace('-', u'\u02d7')
+        if ctrl_text:
+            ctrl_text = "${}$".format(ctrl_text[0].upper() + ctrl_text[1:])
+            ctrl_text = ctrl_text.replace(' ', '\\;')
+            ctrl_text = ctrl_text.replace('-', u'\u02d7')
+        return gate_text, ctrl_text
+
+    def _get_colors(self, op):
+        if op.name in self._style.dispcol:
+            fc = self._style.dispcol[op.name]
+        else:
+            fc = self._style.gc
+        if self._style.name != 'bw':
+            ec = fc
+            lc = fc
+        else:
+            ec = self._style.edge_color
+            lc = self._style.lc
+        if op.name == 'reset':
+            gt = self._style.not_gate_lc
+        else:
+            gt = self._style.gt
+        return fc, ec, gt, self._style.tc, self._style.sc, lc
+
+    def _multiqubit_gate(self, xy, fc=None, ec=None, gt=None, sc=None, text='', subtext=''):
+        xpos = min([x[0] for x in xy])
+        ypos = min([y[1] for y in xy])
+        ypos_max = max([y[1] for y in xy])
+
+        # added .21 is for qubit numbers on the left side
+        text_width = self._get_text_width(text, self._style.fs) + .21
+        sub_width = self._get_text_width(subtext, self._style.sfs) + .21
+        wid = max((text_width, sub_width, WID))
 
         qubit_span = abs(ypos) - abs(ypos_max) + 1
         height = HIG + (qubit_span - 1)
         box = patches.Rectangle(
-            xy=(xpos - 0.5 * wid, ypos - .5 * HIG),
-            width=wid, height=height,
-            fc=_fc,
-            ec=self._style.dispcol['multi'],
-            linewidth=1.5, zorder=PORDER_GATE)
+            xy=(xpos - 0.5 * wid, ypos - .5 * HIG), width=wid, height=height,
+            fc=fc, ec=ec, linewidth=1.5, zorder=PORDER_GATE)
         self.ax.add_patch(box)
-        # Annotate inputs
+
+        # annotate inputs
         for bit, y in enumerate([x[1] for x in xy]):
-            self.ax.text(xpos - 0.45 * wid, y, str(bit), ha='left', va='center',
-                         fontsize=self._scale * self._style.fs, color=self._style.gt,
+            self.ax.text(xpos + .07 - 0.5 * wid, y, str(bit), ha='left', va='center',
+                         fontsize=self._style.fs, color=gt,
                          clip_on=True, zorder=PORDER_TEXT)
-
         if text:
-
-            disp_text = text
             if subtext:
-                self.ax.text(xpos, ypos + 0.5 * height, disp_text, ha='center',
-                             va='center', fontsize=self._scale * self._style.fs,
-                             color=self._style.gt, clip_on=True,
+                self.ax.text(xpos+.11, ypos + 0.4 * height, text, ha='center',
+                             va='center', fontsize=self._style.fs,
+                             color=gt, clip_on=True,
                              zorder=PORDER_TEXT)
-                self.ax.text(xpos, ypos + 0.3 * height, subtext, ha='center',
-                             va='center', fontsize=self._scale * self._style.sfs,
-                             color=self._style.sc, clip_on=True,
+                self.ax.text(xpos+.11, ypos + 0.2 * height, subtext, ha='center',
+                             va='center', fontsize=self._style.sfs,
+                             color=sc, clip_on=True,
                              zorder=PORDER_TEXT)
             else:
-                self.ax.text(xpos, ypos + .5 * (qubit_span - 1), disp_text,
-                             ha='center',
-                             va='center',
-                             fontsize=self._scale * self._style.fs,
-                             color=self._style.gt,
-                             clip_on=True,
-                             zorder=PORDER_TEXT,
-                             wrap=True)
-
-    def _gate(self, xy, fc=None, wide=False, text=None, subtext=None):
+                self.ax.text(xpos+.11, ypos + .5 * (qubit_span - 1), text,
+                             ha='center', va='center', fontsize=self._style.fs,
+                             color=gt, clip_on=True,
+                             zorder=PORDER_TEXT, wrap=True)
+
+    def _gate(self, xy, fc=None, ec=None, gt=None, sc=None, text='', subtext=''):
         xpos, ypos = xy
 
-        if wide:
-            if subtext:
-                subtext_len = len(subtext)
-                if '$\\pi$' in subtext:
-                    pi_count = subtext.count('pi')
-                    subtext_len = subtext_len - (4 * pi_count)
+        text_width = self._get_text_width(text, self._style.fs)
+        sub_width = self._get_text_width(subtext, self._style.sfs)
+        wid = max((text_width, sub_width, WID))
 
-                boxes_wide = round(max(subtext_len, len(text)) / 10, 1) or 1
-                wid = WID * 1.5 * boxes_wide
-            else:
-                boxes_wide = round(len(text) / 10) or 1
-                wid = WID * 2.2 * boxes_wide
-            if wid < WID:
-                wid = WID
-        else:
-            wid = WID
-        if fc:
-            _fc = fc
-        elif self._style.gc != DefaultStyle().gc:
-            _fc = self._style.gc
-        elif text and text in self._style.dispcol:
-            _fc = self._style.dispcol[text]
-        else:
-            _fc = self._style.gc
-
-        box = patches.Rectangle(
-            xy=(xpos - 0.5 * wid, ypos - 0.5 * HIG), width=wid, height=HIG,
-            fc=_fc, ec=self._style.edge_color, linewidth=1.5, zorder=PORDER_GATE)
+        box = patches.Rectangle(xy=(xpos - 0.5 * wid, ypos - 0.5 * HIG),
+                                width=wid, height=HIG, fc=fc, ec=ec,
+                                linewidth=1.5, zorder=PORDER_GATE)
         self.ax.add_patch(box)
 
         if text:
-            font_size = self._style.fs
-            sub_font_size = self._style.sfs
-            # check if gate is not unitary
-            if text in ['reset']:
-                disp_color = self._style.not_gate_lc
-                sub_color = self._style.not_gate_lc
-                font_size = self._style.math_fs
-
-            else:
-                disp_color = self._style.gt
-                sub_color = self._style.sc
-
-            if text in self._style.dispcol:
-                disp_text = "${}$".format(self._style.disptex[text])
-            else:
-                disp_text = text
             if subtext:
-                self.ax.text(xpos, ypos + 0.15 * HIG, disp_text, ha='center',
-                             va='center', fontsize=self._scale * font_size,
-                             color=disp_color, clip_on=True,
-                             zorder=PORDER_TEXT)
+                self.ax.text(xpos, ypos + 0.15 * HIG, text, ha='center',
+                             va='center', fontsize=self._style.fs, color=gt,
+                             clip_on=True, zorder=PORDER_TEXT)
                 self.ax.text(xpos, ypos - 0.3 * HIG, subtext, ha='center',
-                             va='center', fontsize=self._scale * sub_font_size,
-                             color=sub_color, clip_on=True,
-                             zorder=PORDER_TEXT)
+                             va='center', fontsize=self._style.sfs, color=sc,
+                             clip_on=True, zorder=PORDER_TEXT)
             else:
-                self.ax.text(xpos, ypos, disp_text, ha='center', va='center',
-                             fontsize=self._scale * font_size,
-                             color=disp_color,
-                             clip_on=True,
-                             zorder=PORDER_TEXT)
-
-    def _subtext(self, xy, text):
-        xpos, ypos = xy
-
-        self.ax.text(xpos, ypos - 0.3 * HIG, text, ha='center', va='top',
-                     fontsize=self._scale * self._style.sfs,
-                     color=self._style.tc,
-                     clip_on=True,
-                     zorder=PORDER_TEXT)
+                self.ax.text(xpos, ypos, text, ha='center', va='center',
+                             fontsize=self._style.fs, color=gt,
+                             clip_on=True, zorder=PORDER_TEXT)
 
-    def _sidetext(self, xy, text):
+    def _sidetext(self, xy, tc=None, text=''):
         xpos, ypos = xy
 
-        # 0.15 = the initial gap, each char means it needs to move
-        # another 0.0375 over
-        xp = xpos + 0.15 + (0.0375 * len(text))
+        # 0.08 = the initial gap, add 1/2 text width to place on the right
+        text_width = self._get_text_width(text, self._style.sfs)
+        xp = xpos + 0.08 + text_width / 2
         self.ax.text(xp, ypos + HIG, text, ha='center', va='top',
-                     fontsize=self._scale * self._style.sfs,
-                     color=self._style.tc,
-                     clip_on=True,
-                     zorder=PORDER_TEXT)
+                     fontsize=self._style.sfs, color=tc,
+                     clip_on=True, zorder=PORDER_TEXT)
 
     def _line(self, xy0, xy1, lc=None, ls=None, zorder=PORDER_LINE):
         x0, y0 = xy0
         x1, y1 = xy1
-        if lc is None:
-            linecolor = self._style.lc
-        else:
-            linecolor = lc
-        if ls is None:
-            linestyle = 'solid'
-        else:
-            linestyle = ls
+        linecolor = self._style.lc if lc is None else lc
+        linestyle = 'solid' if ls is None else ls
 
         if linestyle == 'doublet':
             theta = np.arctan2(np.abs(x1 - x0), np.abs(y1 - y0))
             dx = 0.05 * WID * np.cos(theta)
             dy = 0.05 * WID * np.sin(theta)
             self.ax.plot([x0 + dx, x1 + dx], [y0 + dy, y1 + dy],
-                         color=linecolor,
-                         linewidth=2,
-                         linestyle='solid',
-                         zorder=zorder)
+                         color=linecolor, linewidth=2,
+                         linestyle='solid', zorder=zorder)
             self.ax.plot([x0 - dx, x1 - dx], [y0 - dy, y1 - dy],
-                         color=linecolor,
-                         linewidth=2,
-                         linestyle='solid',
-                         zorder=zorder)
+                         color=linecolor, linewidth=2,
+                         linestyle='solid', zorder=zorder)
         else:
             self.ax.plot([x0, x1], [y0, y1],
-                         color=linecolor,
-                         linewidth=2,
-                         linestyle=linestyle,
-                         zorder=zorder)
+                         color=linecolor, linewidth=2,
+                         linestyle=linestyle, zorder=zorder)
 
-    def _measure(self, qxy, cxy, cid):
+    def _measure(self, qxy, cxy, cid, fc=None, ec=None, gt=None, sc=None):
         qx, qy = qxy
         cx, cy = cxy
 
-        self._gate(qxy, fc=self._style.dispcol['meas'])
+        # draw gate box
+        self._gate(qxy, fc=fc, ec=ec, gt=gt, sc=sc)
 
         # add measure symbol
         arc = patches.Arc(xy=(qx, qy - 0.15 * HIG), width=WID * 0.7,
                           height=HIG * 0.7, theta1=0, theta2=180, fill=False,
-                          ec=self._style.not_gate_lc, linewidth=2,
-                          zorder=PORDER_GATE)
+                          ec=self._style.not_gate_lc, linewidth=2, zorder=PORDER_GATE)
         self.ax.add_patch(arc)
-        self.ax.plot([qx, qx + 0.35 * WID],
-                     [qy - 0.15 * HIG, qy + 0.20 * HIG],
+        self.ax.plot([qx, qx + 0.35 * WID], [qy - 0.15 * HIG, qy + 0.20 * HIG],
                      color=self._style.not_gate_lc, linewidth=2, zorder=PORDER_GATE)
         # arrow
-        self._line(qxy, [cx, cy + 0.35 * WID], lc=self._style.cc,
-                   ls=self._style.cline)
+        self._line(qxy, [cx, cy + 0.35 * WID], lc=self._style.cc, ls=self._style.cline)
         arrowhead = patches.Polygon(((cx - 0.20 * WID, cy + 0.35 * WID),
                                      (cx + 0.20 * WID, cy + 0.35 * WID),
-                                     (cx, cy)),
-                                    fc=self._style.cc,
-                                    ec=None)
+                                     (cx, cy)), fc=self._style.cc, ec=None)
         self.ax.add_artist(arrowhead)
         # target
-        if self._style.bundle:
+        if self.cregbundle:
             self.ax.text(cx + .25, cy + .1, str(cid), ha='left', va='bottom',
-                         fontsize=self._scale * 0.8 * self._style.fs,
-                         color=self._style.tc,
-                         clip_on=True,
-                         zorder=PORDER_TEXT)
+                         fontsize=0.8 * self._style.fs, color=self._style.tc,
+                         clip_on=True, zorder=PORDER_TEXT)
 
     def _conds(self, xy, istrue=False):
         xpos, ypos = xy
 
-        if istrue:
-            _fc = self._style.lc
-        else:
-            _fc = self._style.gc
-
-        box = patches.Circle(xy=(xpos, ypos), radius=WID * 0.15,
-                             fc=_fc, ec=self._style.lc,
-                             linewidth=1.5, zorder=PORDER_GATE)
+        fc = self._style.lc if istrue else self._style.bg
+        box = patches.Circle(xy=(xpos, ypos), radius=WID * 0.15, fc=fc,
+                             ec=self._style.lc, linewidth=1.5, zorder=PORDER_GATE)
         self.ax.add_patch(box)
 
-    def _ctrl_qubit(self, xy, fc=None, ec=None):
-        if self._style.gc != DefaultStyle().gc:
-            fc = self._style.gc
-            ec = self._style.gc
-        if fc is None:
-            fc = self._style.lc
-        if ec is None:
-            ec = self._style.lc
+    def _ctrl_qubit(self, xy, fc=None, ec=None, tc=None, text='', text_top=None):
         xpos, ypos = xy
         box = patches.Circle(xy=(xpos, ypos), radius=WID * 0.15,
-                             fc=fc, ec=ec,
-                             linewidth=1.5, zorder=PORDER_GATE)
+                             fc=fc, ec=ec, linewidth=1.5, zorder=PORDER_GATE)
         self.ax.add_patch(box)
+        # display the control label at the top or bottom if there is one
+        if text_top is True:
+            self.ax.text(xpos, ypos + 0.7 * HIG, text, ha='center', va='top',
+                         fontsize=self._style.sfs, color=self._style.tc,
+                         clip_on=True, zorder=PORDER_TEXT)
+        elif text_top is False:
+            self.ax.text(xpos, ypos - 0.3 * HIG, text, ha='center', va='top',
+                         fontsize=self._style.sfs, color=tc,
+                         clip_on=True, zorder=PORDER_TEXT)
 
-    def set_multi_ctrl_bits(self, ctrl_state, num_ctrl_qubits, qbit, color_str):
-        # convert op.ctrl_state to bit string and reverse
+    def _set_ctrl_bits(self, ctrl_state, num_ctrl_qubits, qbit, ec=None, tc=None,
+                       text='', qargs=None):
+        # place the control label at the top or bottom of controls
+        if text:
+            qlist = [qubit.index for qubit in qargs]
+            ctbits = qlist[:num_ctrl_qubits]
+            qubits = qlist[num_ctrl_qubits:]
+            max_ctbit = max(ctbits)
+            min_ctbit = min(ctbits)
+            top = min(qubits) > min_ctbit
+
+        # display the control qubits as open or closed based on ctrl_state
         cstate = "{0:b}".format(ctrl_state).rjust(num_ctrl_qubits, '0')[::-1]
         for i in range(num_ctrl_qubits):
-            # Make facecolor of ctrl bit the box color if closed and bkgrnd if open
-            fc_open_close = (self._style.dispcol[color_str] if cstate[i] == '1'
-                             else self._style.bg)
-            self._ctrl_qubit(qbit[i], fc=fc_open_close, ec=self._style.dispcol[color_str])
-
-    def _tgt_qubit(self, xy, fc=None, ec=None, ac=None,
-                   add_width=None):
-        if self._style.gc != DefaultStyle().gc:
-            fc = self._style.gc
-            ec = self._style.gc
-        if fc is None:
-            fc = self._style.dispcol['target']
-        if ec is None:
-            ec = self._style.lc
-        if ac is None:
-            ac = self._style.lc
-        if add_width is None:
-            add_width = 0.35
-
+            fc_open_close = ec if cstate[i] == '1' else self._style.bg
+            text_top = None
+            if text:
+                if top and qlist[i] == min_ctbit:
+                    text_top = True
+                elif not top and qlist[i] == max_ctbit:
+                    text_top = False
+            self._ctrl_qubit(qbit[i], fc=fc_open_close, ec=ec, tc=tc,
+                             text=text, text_top=text_top)
+
+    def _x_tgt_qubit(self, xy, ec=None, ac=None):
         linewidth = 2
-
-        if self._style.dispcol['target'] == '#ffffff':
-            add_width = self._style.colored_add_width
-
         xpos, ypos = xy
-
         box = patches.Circle(xy=(xpos, ypos), radius=HIG * 0.35,
-                             fc=fc, ec=ec, linewidth=linewidth,
+                             fc=ec, ec=ec, linewidth=linewidth,
                              zorder=PORDER_GATE)
         self.ax.add_patch(box)
+
         # add '+' symbol
-        self.ax.plot([xpos, xpos], [ypos - add_width * HIG,
-                                    ypos + add_width * HIG],
+        self.ax.plot([xpos, xpos], [ypos - 0.2 * HIG, ypos + 0.2 * HIG],
+                     color=ac, linewidth=linewidth, zorder=PORDER_GATE + 1)
+        self.ax.plot([xpos - 0.2 * HIG, xpos + 0.2 * HIG], [ypos, ypos],
                      color=ac, linewidth=linewidth, zorder=PORDER_GATE + 1)
 
-        self.ax.plot([xpos - add_width * HIG, xpos + add_width * HIG],
-                     [ypos, ypos], color=ac, linewidth=linewidth,
-                     zorder=PORDER_GATE + 1)
-
-    def _swap(self, xy, color):
+    def _swap(self, xy, color=None):
         xpos, ypos = xy
 
         self.ax.plot([xpos - 0.20 * WID, xpos + 0.20 * WID],
@@ -478,18 +528,11 @@ def _swap(self, xy, color):
 
     def _barrier(self, config):
         xys = config['coord']
-        group = config['group']
-        y_reg = []
-        for qreg in self._qreg_dict.values():
-            if qreg['group'] in group:
-                y_reg.append(qreg['y'])
-
         for xy in xys:
             xpos, ypos = xy
             self.ax.plot([xpos, xpos], [ypos + 0.5, ypos - 0.5],
                          linewidth=1, linestyle="dashed",
-                         color=self._style.lc,
-                         zorder=PORDER_TEXT)
+                         color=self._style.lc, zorder=PORDER_TEXT)
             box = patches.Rectangle(xy=(xpos - (0.3 * WID), ypos - 0.5),
                                     width=0.6 * WID, height=1,
                                     fc=self._style.bc, ec=None, alpha=0.6,
@@ -515,15 +558,17 @@ def draw(self, filename=None, verbose=False):
         _yt = self._style.margin[3] + 0.5
         self.ax.set_xlim(_xl, _xr)
         self.ax.set_ylim(_yb, _yt)
+
         # update figure size
         fig_w = _xr - _xl
         fig_h = _yt - _yb
         if self._style.figwidth < 0.0:
-            self._style.figwidth = fig_w * 4.3 * self._scale * self._style.fs / 72 / WID
+            self._style.figwidth = fig_w * self._scale * self._style.fs / 72 / WID
         self.figure.set_size_inches(self._style.figwidth, self._style.figwidth * fig_h / fig_w)
+
         if filename:
             self.figure.savefig(filename, dpi=self._style.dpi,
-                                bbox_inches='tight')
+                                bbox_inches='tight', facecolor=self.figure.get_facecolor())
         if self.return_fig:
             if get_backend() in ['module://ipykernel.pylab.backend_inline',
                                  'nbAgg']:
@@ -531,6 +576,13 @@ def draw(self, filename=None, verbose=False):
             return self.figure
 
     def _draw_regs(self):
+        longest_label_width = 0
+        if self.initial_state:
+            initial_qbit = ' |0>'
+            initial_cbit = ' 0'
+        else:
+            initial_qbit = ''
+            initial_cbit = ''
 
         def _fix_double_script(label):
             words = label.split(' ')
@@ -538,117 +590,100 @@ def _fix_double_script(label):
                      for word in words]
             words = [word.replace('^', r'\^{\ }') if word.count('^') > 1 else word
                      for word in words]
-            return ' '.join(words)
+            label = ' '.join(words).replace(' ', '\\;')
+            return label
 
-        len_longest_label = 0
         # quantum register
         for ii, reg in enumerate(self._qreg):
             if len(self._qreg) > 1:
                 if self.layout is None:
                     label = '${{{name}}}_{{{index}}}$'.format(name=reg.register.name,
                                                               index=reg.index)
+                    label = _fix_double_script(label) + initial_qbit
+                    text_width = self._get_text_width(label, self._style.fs)
                 else:
                     label = '${{{name}}}_{{{index}}} \\mapsto {{{physical}}}$'.format(
                         name=self.layout[reg.index].register.name,
-                        index=self.layout[reg.index].index,
-                        physical=reg.index)
+                        index=self.layout[reg.index].index, physical=reg.index)
+                    label = _fix_double_script(label) + initial_qbit
+                    text_width = self._get_text_width(label, self._style.fs)
             else:
                 label = '${name}$'.format(name=reg.register.name)
+                label = _fix_double_script(label) + initial_qbit
+                text_width = self._get_text_width(label, self._style.fs)
 
-            label = _fix_double_script(label)
-            if len(label) > len_longest_label:
-                len_longest_label = len(label)
+            text_width = text_width * 1.15  # to account for larger font used
+            if text_width > longest_label_width:
+                longest_label_width = text_width
 
             pos = -ii
             self._qreg_dict[ii] = {
-                'y': pos,
-                'label': label,
-                'index': reg.index,
-                'group': reg.register
-            }
+                'y': pos, 'label': label, 'index': reg.index, 'group': reg.register}
             self._cond['n_lines'] += 1
+
         # classical register
         if self._creg:
             n_creg = self._creg.copy()
             n_creg.pop(0)
             idx = 0
             y_off = -len(self._qreg)
-            for ii, (reg, nreg) in enumerate(itertools.zip_longest(
-                    self._creg, n_creg)):
+            for ii, (reg, nreg) in enumerate(itertools.zip_longest(self._creg, n_creg)):
                 pos = y_off - idx
-                if self._style.bundle:
+                if self.cregbundle:
                     label = '${}$'.format(reg.register.name)
-                    label = _fix_double_script(label)
-                    self._creg_dict[ii] = {
-                        'y': pos,
-                        'label': label,
-                        'index': reg.index,
-                        'group': reg.register
-                    }
+                    label = _fix_double_script(label) + initial_cbit
+                    text_width = self._get_text_width(reg.register.name, self._style.fs) * 1.15
+                    if text_width > longest_label_width:
+                        longest_label_width = text_width
+                    self._creg_dict[ii] = {'y': pos, 'label': label, 'index': reg.index,
+                                           'group': reg.register}
                     if not (not nreg or reg.register != nreg.register):
                         continue
                 else:
                     label = '${}_{{{}}}$'.format(reg.register.name, reg.index)
-                    label = _fix_double_script(label)
-                    self._creg_dict[ii] = {
-                        'y': pos,
-                        'label': label,
-                        'index': reg.index,
-                        'group': reg.register
-                    }
-                if len(label) > len_longest_label:
-                    len_longest_label = len(label)
-
+                    label = _fix_double_script(label) + initial_cbit
+                    text_width = self._get_text_width(reg.register.name, self._style.fs) * 1.15
+                    if text_width > longest_label_width:
+                        longest_label_width = text_width
+                    self._creg_dict[ii] = {'y': pos, 'label': label, 'index': reg.index,
+                                           'group': reg.register}
                 self._cond['n_lines'] += 1
                 idx += 1
 
-        # 7 is the length of the smallest possible label
-        self.x_offset = -.5 + 0.18 * (len_longest_label - 7)
+        self._reg_long_text = longest_label_width
+        self.x_offset = -1.2 + self._reg_long_text
 
     def _draw_regs_sub(self, n_fold, feedline_l=False, feedline_r=False):
         # quantum register
         for qreg in self._qreg_dict.values():
-            if n_fold == 0:
-                label = qreg['label']
-            else:
-                label = qreg['label']
+            label = qreg['label']
             y = qreg['y'] - n_fold * (self._cond['n_lines'] + 1)
             self.ax.text(self.x_offset - 0.2, y, label, ha='right', va='center',
-                         fontsize=self._scale * 1.25 * self._style.fs,
-                         color=self._style.tc,
-                         clip_on=True,
-                         zorder=PORDER_TEXT)
+                         fontsize=1.25 * self._style.fs, color=self._style.tc,
+                         clip_on=True, zorder=PORDER_TEXT)
             self._line([self.x_offset + 0.2, y], [self._cond['xmax'], y],
                        zorder=PORDER_REGLINE)
+
         # classical register
         this_creg_dict = {}
         for creg in self._creg_dict.values():
-            if n_fold == 0:
-                label = creg['label']
-            else:
-                label = creg['label']
+            label = creg['label']
             y = creg['y'] - n_fold * (self._cond['n_lines'] + 1)
             if y not in this_creg_dict.keys():
                 this_creg_dict[y] = {'val': 1, 'label': label}
             else:
                 this_creg_dict[y]['val'] += 1
         for y, this_creg in this_creg_dict.items():
-            # bundle
+            # cregbundle
             if this_creg['val'] > 1:
-                self.ax.plot([self.x_offset + 1.1, self.x_offset + 1.2], [y - .1, y + .1],
-                             color=self._style.cc,
-                             zorder=PORDER_LINE)
-                self.ax.text(self.x_offset + 1.0, y + .1, str(this_creg['val']), ha='left',
-                             va='bottom',
-                             fontsize=self._scale * 0.8 * self._style.fs,
-                             color=self._style.tc,
-                             clip_on=True,
-                             zorder=PORDER_TEXT)
+                self.ax.plot([self.x_offset + 0.64, self.x_offset + 0.74], [y - .1, y + .1],
+                             color=self._style.cc, zorder=PORDER_LINE)
+                self.ax.text(self.x_offset+0.54, y + .1, str(this_creg['val']), ha='left',
+                             va='bottom', fontsize=0.8 * self._style.fs,
+                             color=self._style.tc, clip_on=True, zorder=PORDER_TEXT)
             self.ax.text(self.x_offset - 0.2, y, this_creg['label'], ha='right', va='center',
-                         fontsize=self._scale * 1.5 * self._style.fs,
-                         color=self._style.tc,
-                         clip_on=True,
-                         zorder=PORDER_TEXT)
+                         fontsize=1.25 * self._style.fs, color=self._style.tc,
+                         clip_on=True, zorder=PORDER_TEXT)
             self._line([self.x_offset + 0.2, y], [self._cond['xmax'], y], lc=self._style.cc,
                        ls=self._style.cline, zorder=PORDER_REGLINE)
 
@@ -661,7 +696,9 @@ def _draw_regs_sub(self, n_fold, feedline_l=False, feedline_r=False):
                                  - n_fold * (self._cond['n_lines'] + 1)))
 
     def _draw_ops(self, verbose=False):
-        _wide_gate = ['u2', 'u3', 'cu3', 'unitary', 'r', 'cu1', 'rzz']
+        _standard_gates = ['x', 'y', 'z', 'id', 'h', 'r', 's', 'sdg', 't', 'tdg', 'rx', 'ry', 'rz',
+                           'rxx', 'ryy', 'rzx', 'u1', 'u2', 'u3', 'swap', 'reset']
+        _barrier_gates = ['barrier', 'snapshot', 'load', 'save', 'noise']
         _barriers = {'coord': [], 'group': []}
 
         #
@@ -670,98 +707,73 @@ def _draw_ops(self, verbose=False):
         q_anchors = {}
         for key, qreg in self._qreg_dict.items():
             q_anchors[key] = Anchor(reg_num=self._cond['n_lines'],
-                                    yind=qreg['y'],
-                                    fold=self.fold)
+                                    yind=qreg['y'], fold=self.fold)
         c_anchors = {}
         for key, creg in self._creg_dict.items():
             c_anchors[key] = Anchor(reg_num=self._cond['n_lines'],
-                                    yind=creg['y'],
-                                    fold=self.fold)
+                                    yind=creg['y'], fold=self.fold)
         #
-        # draw gates
+        # draw the ops
         #
         prev_anc = -1
         for layer in self._ops:
-            layer_width = 1
-
+            widest_box = 0.0
+            #
+            # compute the layer_width for this layer
+            #
             for op in layer:
-                # If one of the standard wide gates
-                if op.name in _wide_gate:
-                    if layer_width < 2:
-                        layer_width = 2
-                    if op.type == 'op' and hasattr(op.op, 'params'):
-                        param = self.param_parse(op.op.params)
-                        if '$\\pi$' in param:
-                            pi_count = param.count('pi')
-                            len_param = len(param) - (4 * pi_count)
-                        else:
-                            len_param = len(param)
-                        if len_param > len(op.name):
-                            box_width = math.floor(len(param) / 10)
-                            if op.name == 'unitary':
-                                box_width = 2
-                            # If more than 4 characters min width is 2
-                            if box_width <= 1:
-                                box_width = 2
-                            if layer_width < box_width:
-                                if box_width > 2:
-                                    layer_width = box_width
-                                else:
-                                    layer_width = 2
-                            continue
-
-                # If custom ControlledGate
-                elif isinstance(op.op, ControlledGate) and op.name not in [
-                        'ccx', 'cx', 'c3x', 'c4x', 'cy', 'cz', 'ch', 'cu1',
-                        'cu3', 'crz', 'cswap']:
-                    if op.type == 'op' and hasattr(op.op, 'params'):
-                        param = self.param_parse(op.op.params)
-                        if '$\\pi$' in param:
-                            pi_count = param.count('pi')
-                            len_param = len(param) - (4 * pi_count)
-                        else:
-                            len_param = len(param)
-                        if len_param > len(op.name):
-                            box_width = math.floor(len_param / 5.5)
-                            layer_width = box_width
-                            continue
-
-                # if custom gate with a longer than standard name determine
-                # width
-                elif op.name not in ['barrier', 'snapshot', 'load', 'save',
-                                     'noise', 'cswap', 'swap', 'measure'] and len(op.name) >= 4:
-                    box_width = math.ceil(len(op.name) / 6)
-
-                    # handle params/subtext longer than op names
-                    if op.type == 'op' and hasattr(op.op, 'params'):
-                        param = self.param_parse(op.op.params)
-                        if '$\\pi$' in param:
-                            pi_count = param.count('pi')
-                            len_param = len(param) - (4 * pi_count)
-                        else:
-                            len_param = len(param)
-                        if len_param > len(op.name):
-                            box_width = math.floor(len(param) / 8)
-                            # If more than 4 characters min width is 2
-                            if box_width <= 1:
-                                box_width = 2
-                            if layer_width < box_width:
-                                if box_width > 2:
-                                    layer_width = box_width * 2
-                                else:
-                                    layer_width = 2
-                            continue
-                    # If more than 4 characters min width is 2
-                    layer_width = math.ceil(box_width * WID * 2.5)
+                if op.name in [*_barrier_gates, 'measure']:
+                    continue
+
+                base_name = None if not hasattr(op.op, 'base_gate') else op.op.base_gate.name
+                gate_text, ctrl_text = self._get_gate_ctrl_text(op)
+
+                # if a standard_gate, no params, and no labels, layer_width is 1
+                if (not hasattr(op.op, 'params') and
+                        ((op.name in _standard_gates or base_name in _standard_gates)
+                         and gate_text in (op.name, base_name) and ctrl_text is None)):
+                    continue
+
+                # small increments at end of the 3 _get_text_width calls are for small
+                # spacing adjustments between gates
+                ctrl_width = self._get_text_width(ctrl_text, fontsize=self._style.sfs) - 0.05
+
+                # get param_width, but 0 for gates with array params
+                if (hasattr(op.op, 'params')
+                        and not any([isinstance(param, np.ndarray) for param in op.op.params])
+                        and len(op.op.params) > 0):
+                    param = self.param_parse(op.op.params)
+                    if op.name == 'initialize':
+                        param = '[%s]' % param
+                    param = "${}$".format(param)
+                    param_width = self._get_text_width(param, fontsize=self._style.sfs) + 0.08
+                else:
+                    param_width = 0.0
 
-            this_anc = prev_anc + 1
+                if op.name == 'cu1' or op.name == 'rzz' or base_name == 'rzz':
+                    tname = 'U1' if op.name == 'cu1' else 'zz'
+                    gate_width = (self._get_text_width(tname + ' ()$$',
+                                                       fontsize=self._style.sfs)
+                                  + param_width) * 1.5
+                else:
+                    gate_width = self._get_text_width(gate_text, fontsize=self._style.fs) + 0.10
+                    # add .21 for the qubit numbers on the left of the multibit gates
+                    if (op.name not in _standard_gates and base_name not in _standard_gates):
+                        gate_width += 0.21
+
+                box_width = max((gate_width, ctrl_width, param_width, WID))
+                if box_width > widest_box:
+                    widest_box = box_width
 
+            layer_width = int(widest_box) + 1
+            this_anc = prev_anc + 1
+            #
+            # draw the gates in this layer
+            #
             for op in layer:
-                _iswide = op.name in _wide_gate
-                if op.name not in ['barrier', 'snapshot', 'load', 'save',
-                                   'noise', 'cswap', 'swap', 'measure',
-                                   'reset'] and len(op.name) >= 4:
-                    _iswide = True
+                base_name = None if not hasattr(op.op, 'base_gate') else op.op.base_gate.name
+                gate_text, ctrl_text = self._get_gate_ctrl_text(op)
+                fc, ec, gt, tc, sc, lc = self._get_colors(op)
 
                 # get qreg index
                 q_idxs = []
@@ -781,13 +793,10 @@ def _draw_ops(self, verbose=False):
                             c_idxs.append(index)
                             break
 
-                # Only add the gate to the anchors if it is going to be plotted.
-                # This prevents additional blank wires at the end of the line if
+                # only add the gate to the anchors if it is going to be plotted.
+                # this prevents additional blank wires at the end of the line if
                 # the last instruction is a barrier type
-                if self.plot_barriers or \
-                        op.name not in ['barrier', 'snapshot', 'load', 'save',
-                                        'noise']:
-
+                if self.plot_barriers or op.name not in _barrier_gates:
                     for ii in q_idxs:
                         q_anchors[ii].set_index(this_anc, layer_width)
 
@@ -807,10 +816,13 @@ def _draw_ops(self, verbose=False):
                 if verbose:
                     print(op)
 
-                if op.type == 'op' and hasattr(op.op, 'params'):
-                    param = self.param_parse(op.op.params)
+                # load param
+                if (op.type == 'op' and hasattr(op.op, 'params') and len(op.op.params) > 0
+                        and not any([isinstance(param, np.ndarray) for param in op.op.params])):
+                    param = "${}$".format(self.param_parse(op.op.params))
                 else:
-                    param = None
+                    param = ''
+
                 # conditional gate
                 if op.condition:
                     c_xy = [c_anchors[ii].plot_coord(this_anc, layer_width, self.x_offset) for
@@ -832,14 +844,17 @@ def _draw_ops(self, verbose=False):
                     for xy, m in zip(c_xy, cmask):
                         if m == '1':
                             if xy not in xy_plot:
-                                if vlist[v_ind] == '1' or self._style.bundle:
+                                if vlist[v_ind] == '1' or self.cregbundle:
                                     self._conds(xy, istrue=True)
                                 else:
                                     self._conds(xy, istrue=False)
                                 xy_plot.append(xy)
                             v_ind += 1
                     creg_b = sorted(xy_plot, key=lambda xy: xy[1])[0]
-                    self._subtext(creg_b, hex(val))
+                    xpos, ypos = creg_b
+                    self.ax.text(xpos, ypos - 0.3 * HIG, hex(val), ha='center', va='top',
+                                 fontsize=self._style.sfs, color=self._style.tc,
+                                 clip_on=True, zorder=PORDER_TEXT)
                     self._line(qreg_t, creg_b, lc=self._style.cc,
                                ls=self._style.cline)
                 #
@@ -847,229 +862,110 @@ def _draw_ops(self, verbose=False):
                 #
                 if op.name == 'measure':
                     vv = self._creg_dict[c_idxs[0]]['index']
-                    self._measure(q_xy[0], c_xy[0], vv)
-                elif op.name in ['barrier', 'snapshot', 'load', 'save',
-                                 'noise']:
+                    self._measure(q_xy[0], c_xy[0], vv, fc=fc, ec=ec, gt=gt, sc=sc)
+
+                elif op.name in _barrier_gates:
                     _barriers = {'coord': [], 'group': []}
                     for index, qbit in enumerate(q_idxs):
                         q_group = self._qreg_dict[qbit]['group']
-
                         if q_group not in _barriers['group']:
                             _barriers['group'].append(q_group)
                         _barriers['coord'].append(q_xy[index])
                     if self.plot_barriers:
                         self._barrier(_barriers)
-                elif op.name == 'initialize':
-                    vec = '[%s]' % param
-                    self._custom_multiqubit_gate(q_xy, wide=_iswide,
-                                                 text=op.op.label or "|psi>",
-                                                 subtext=vec)
-                elif op.name == 'unitary':
-                    # TODO(mtreinish): Look into adding the unitary to the
-                    # subtext
-                    self._custom_multiqubit_gate(q_xy, wide=_iswide,
-                                                 text=op.op.label or "Unitary")
-                elif isinstance(op.op, ControlledGate) and op.name not in [
-                        'ccx', 'cx', 'c3x', 'c4x', 'cy', 'cz', 'ch', 'cu1', 'cu3', 'crz',
-                        'cswap']:
-                    disp = op.op.base_gate.name
-                    num_ctrl_qubits = op.op.num_ctrl_qubits
-                    num_qargs = len(q_xy) - num_ctrl_qubits
-                    # set the ctrl qbits to open or closed
-                    self.set_multi_ctrl_bits(op.op.ctrl_state, num_ctrl_qubits, q_xy, 'multi')
-
-                    # add qubit-qubit wiring
-                    self._line(qreg_b, qreg_t, lc=self._style.dispcol['multi'])
-                    if num_qargs == 1:
-                        if param:
-                            self._gate(q_xy[num_ctrl_qubits], wide=_iswide,
-                                       text=disp,
-                                       fc=self._style.dispcol['multi'],
-                                       subtext='{}'.format(param))
-                        else:
-                            fcx = op.name if op.name in self._style.dispcol else 'multi'
-                            self._gate(q_xy[num_ctrl_qubits], wide=_iswide, text=disp,
-                                       fc=self._style.dispcol[fcx])
-                    else:
-                        self._custom_multiqubit_gate(
-                            q_xy[num_ctrl_qubits:], wide=_iswide, fc=self._style.dispcol['multi'],
-                            text=disp)
 
+                elif op.name == 'initialize':
+                    vec = "$[{}]$".format(param.replace('$', ''))
+                    self._multiqubit_gate(q_xy, fc=fc, ec=ec, gt=gt, sc=sc,
+                                          text=gate_text, subtext=vec)
                 #
                 # draw single qubit gates
                 #
                 elif len(q_xy) == 1:
-                    disp = op.name
-                    if param:
-                        self._gate(q_xy[0], wide=_iswide, text=disp,
-                                   subtext=str(param))
-                    else:
-                        self._gate(q_xy[0], wide=_iswide, text=disp)
-                #
-                # draw multi-qubit gates (n=2)
-                #
-                elif len(q_xy) == 2:
-                    # cx
-                    if op.name == 'cx':
-                        if self._style.dispcol['cx'] != '#ffffff':
-                            add_width = self._style.colored_add_width
-                        else:
-                            add_width = None
-                        num_ctrl_qubits = op.op.num_ctrl_qubits
-                        # set the ctrl qbits to open or closed
-                        self.set_multi_ctrl_bits(op.op.ctrl_state, num_ctrl_qubits, q_xy, 'cx')
-
-                        if self._style.name != 'bw':
-                            self._tgt_qubit(q_xy[1], fc=self._style.dispcol['cx'],
-                                            ec=self._style.dispcol['cx'],
-                                            ac=self._style.dispcol['target'],
-                                            add_width=add_width)
-                        else:
-                            self._tgt_qubit(q_xy[1], fc=self._style.dispcol['target'],
-                                            ec=self._style.dispcol['cx'],
-                                            ac=self._style.dispcol['cx'],
-                                            add_width=add_width)
-                        # add qubit-qubit wiring
-                        self._line(qreg_b, qreg_t, lc=self._style.dispcol['cx'])
-                    # cz for latexmode
-                    elif op.name == 'cz':
-                        disp = op.name.replace('c', '')
-                        if self._style.name != 'bw':
-                            color = self._style.dispcol['cz']
-                            self._ctrl_qubit(q_xy[0],
-                                             fc=color,
-                                             ec=color)
-                            self._ctrl_qubit(q_xy[1],
-                                             fc=color,
-                                             ec=color)
-                        else:
-                            self._ctrl_qubit(q_xy[0])
-                            self._ctrl_qubit(q_xy[1])
-                        # add qubit-qubit wiring
-                        if self._style.name != 'bw':
-                            self._line(qreg_b, qreg_t,
-                                       lc=color)
-                        else:
-                            self._line(qreg_b, qreg_t, zorder=PORDER_LINE + 1)
-                    # control gate
-                    elif op.name in ['cy', 'ch', 'cu3', 'crz']:
-                        disp = op.name.replace('c', '')
-
-                        color = None
-                        if self._style.name != 'bw':
-                            if op.name == 'cy':
-                                color = self._style.dispcol['cy']
-                            else:
-                                color = self._style.dispcol['multi']
-
-                        self._ctrl_qubit(q_xy[0], fc=color, ec=color)
-                        if param:
-                            self._gate(q_xy[1], wide=_iswide,
-                                       text=disp,
-                                       fc=color,
-                                       subtext='{}'.format(param))
-                        else:
-                            self._gate(q_xy[1], wide=_iswide, text=disp,
-                                       fc=color)
-                        # add qubit-qubit wiring
-                        self._line(qreg_b, qreg_t, lc=color)
-
-                    # rzz gate
-                    elif op.name == 'rzz':
-                        color = self._style.dispcol['multi']
-                        self._ctrl_qubit(q_xy[0], fc=color, ec=color)
-                        self._ctrl_qubit(q_xy[1], fc=color, ec=color)
-                        self._sidetext(qreg_b, text='zz({})'.format(param))
-
-                        # add qubit-qubit wiring
-                        self._line(qreg_b, qreg_t, lc=color)
-
-                    # cu1 gate
-                    elif op.name == 'cu1':
-                        color = self._style.dispcol['multi']
-                        self._ctrl_qubit(q_xy[0], fc=color, ec=color)
-                        self._ctrl_qubit(q_xy[1], fc=color, ec=color)
-                        self._sidetext(qreg_b, text='U1 ({})'.format(param))
-
-                        # add qubit-qubit wiring
-                        fc = self._style
-                        self._line(qreg_b, qreg_t, lc=color)
-
-                    # swap gate
-                    elif op.name == 'swap':
-                        self._swap(q_xy[0], self._style.dispcol['swap'])
-                        self._swap(q_xy[1], self._style.dispcol['swap'])
-                        # add qubit-qubit wiring
-                        self._line(qreg_b, qreg_t, lc=self._style.dispcol['swap'])
-
-                    # dcx and iswap gate
-                    elif op.name in ['dcx', 'iswap']:
-                        self._custom_multiqubit_gate(q_xy, c_xy, wide=_iswide,
-                                                     fc=self._style.dispcol[op.name],
-                                                     text=op.op.label or op.name)
-
-                    # Custom gate
-                    else:
-                        self._custom_multiqubit_gate(q_xy, c_xy, wide=_iswide,
-                                                     text=op.op.label or op.name)
+                    self._gate(q_xy[0], fc=fc, ec=ec, gt=gt, sc=sc,
+                               text=gate_text, subtext=str(param))
                 #
-                # draw multi-qubit gates (n=3)
+                # draw controlled and special gates
                 #
-                elif len(q_xy) in range(3, 6):
-                    # cswap gate
-                    if op.name == 'cswap':
-                        self._ctrl_qubit(q_xy[0],
-                                         fc=self._style.dispcol['multi'],
-                                         ec=self._style.dispcol['multi'])
-                        self._swap(q_xy[1], self._style.dispcol['multi'])
-                        self._swap(q_xy[2], self._style.dispcol['multi'])
-                        # add qubit-qubit wiring
-                        self._line(qreg_b, qreg_t, lc=self._style.dispcol['multi'])
-                    # ccx gate
-                    elif op.name == 'ccx' or op.name == 'c3x' or op.name == 'c4x':
-                        num_ctrl_qubits = op.op.num_ctrl_qubits
-                        # set the ctrl qbits to open or closed
-                        self.set_multi_ctrl_bits(op.op.ctrl_state, num_ctrl_qubits, q_xy, 'multi')
-                        if self._style.name != 'bw':
-                            self._tgt_qubit(q_xy[num_ctrl_qubits], fc=self._style.dispcol['multi'],
-                                            ec=self._style.dispcol['multi'],
-                                            ac=self._style.dispcol['target'])
-                        else:
-                            self._tgt_qubit(q_xy[num_ctrl_qubits], fc=self._style.dispcol['target'],
-                                            ec=self._style.dispcol['multi'],
-                                            ac=self._style.dispcol['multi'])
-                        # add qubit-qubit wiring
-                        self._line(qreg_b, qreg_t, lc=self._style.dispcol['multi'])
-                    # custom gate
+                # cx gates
+                elif isinstance(op.op, ControlledGate) and base_name == 'x':
+                    num_ctrl_qubits = op.op.num_ctrl_qubits
+                    self._set_ctrl_bits(op.op.ctrl_state, num_ctrl_qubits,
+                                        q_xy, ec=ec, tc=tc, text=ctrl_text, qargs=op.qargs)
+                    self._x_tgt_qubit(q_xy[num_ctrl_qubits], ec=ec,
+                                      ac=self._style.dispcol['target'])
+                    self._line(qreg_b, qreg_t, lc=lc)
+
+                # cz gate
+                elif op.name == 'cz':
+                    num_ctrl_qubits = op.op.num_ctrl_qubits
+                    self._set_ctrl_bits(op.op.ctrl_state, num_ctrl_qubits,
+                                        q_xy, ec=ec, tc=tc, text=ctrl_text, qargs=op.qargs)
+                    self._ctrl_qubit(q_xy[1], fc=ec, ec=ec, tc=tc)
+                    self._line(qreg_b, qreg_t, lc=lc, zorder=PORDER_LINE + 1)
+
+                # cu1, rzz, and controlled rzz gates (sidetext gates)
+                elif (op.name == 'cu1' or op.name == 'rzz' or base_name == 'rzz'):
+                    num_ctrl_qubits = 0 if op.name == 'rzz' else op.op.num_ctrl_qubits
+                    if op.name != 'rzz':
+                        self._set_ctrl_bits(op.op.ctrl_state, num_ctrl_qubits,
+                                            q_xy, ec=ec, tc=tc, text=ctrl_text, qargs=op.qargs)
+                    self._ctrl_qubit(q_xy[num_ctrl_qubits], fc=ec, ec=ec, tc=tc)
+                    if op.name != 'cu1':
+                        self._ctrl_qubit(q_xy[num_ctrl_qubits+1], fc=ec, ec=ec, tc=tc)
+                    stext = self._style.disptex['u1'] if op.name == 'cu1' else 'zz'
+                    self._sidetext(qreg_b, tc=tc,
+                                   text='${}$'.format(stext)+' '+'({})'.format(param))
+                    self._line(qreg_b, qreg_t, lc=lc)
+
+                # swap gate
+                elif op.name == 'swap':
+                    self._swap(q_xy[0], color=lc)
+                    self._swap(q_xy[1], color=lc)
+                    self._line(qreg_b, qreg_t, lc=lc)
+
+                # cswap gate
+                elif op.name != 'swap' and base_name == 'swap':
+                    num_ctrl_qubits = op.op.num_ctrl_qubits
+                    self._set_ctrl_bits(op.op.ctrl_state, num_ctrl_qubits,
+                                        q_xy, ec=ec, tc=tc, text=ctrl_text, qargs=op.qargs)
+                    self._swap(q_xy[num_ctrl_qubits], color=lc)
+                    self._swap(q_xy[num_ctrl_qubits+1], color=lc)
+                    self._line(qreg_b, qreg_t, lc=lc)
+
+                # all other controlled gates
+                elif isinstance(op.op, ControlledGate):
+                    num_ctrl_qubits = op.op.num_ctrl_qubits
+                    num_qargs = len(q_xy) - num_ctrl_qubits
+                    self._set_ctrl_bits(op.op.ctrl_state, num_ctrl_qubits,
+                                        q_xy, ec=ec, tc=tc, text=ctrl_text, qargs=op.qargs)
+                    self._line(qreg_b, qreg_t, lc=lc)
+                    if num_qargs == 1:
+                        self._gate(q_xy[num_ctrl_qubits], fc=fc, ec=ec, gt=gt, sc=sc,
+                                   text=gate_text, subtext='{}'.format(param))
                     else:
-                        self._custom_multiqubit_gate(q_xy, c_xy, wide=_iswide,
-                                                     text=getattr(op.op, 'label', None) or op.name)
+                        self._multiqubit_gate(q_xy[num_ctrl_qubits:], fc=fc, ec=ec, gt=gt,
+                                              sc=sc, text=gate_text, subtext='{}'.format(param))
 
-                # draw custom multi-qubit gate
-                elif len(q_xy) > 5:
-                    self._custom_multiqubit_gate(q_xy, c_xy, wide=_iswide,
-                                                 text=op.op.label or op.name)
+                # draw multi-qubit gate as final default
                 else:
-                    logger.critical('Invalid gate %s', op)
-                    raise exceptions.VisualizationError('invalid gate {}'.format(op))
+                    self._multiqubit_gate(q_xy, fc=fc, ec=ec, gt=gt, sc=sc,
+                                          text=gate_text, subtext='{}'.format(param))
 
             # adjust the column if there have been barriers encountered, but not plotted
             barrier_offset = 0
             if not self.plot_barriers:
                 # only adjust if everything in the layer wasn't plotted
-                barrier_offset = -1 if all([op.name in
-                                            ['barrier', 'snapshot', 'load', 'save', 'noise']
-                                            for op in layer]) else 0
+                barrier_offset = -1 if all([op.name in _barrier_gates for op in layer]) else 0
+
             prev_anc = this_anc + layer_width + barrier_offset - 1
         #
         # adjust window size and draw horizontal lines
         #
         anchors = [q_anchors[ii].get_index() for ii in self._qreg_dict]
-        if anchors:
-            max_anc = max(anchors)
-        else:
-            max_anc = 0
-        n_fold = max(0, max_anc - 1) // self.fold
+        max_anc = max(anchors) if anchors else 0
+        n_fold = max(0, max_anc - 1) // self.fold if self.fold > 0 else 0
+
         # window size
         if max_anc > self.fold > 0:
             self._cond['xmax'] = self.fold + 1 + self.x_offset
@@ -1077,64 +973,22 @@ def _draw_ops(self, verbose=False):
         else:
             self._cond['xmax'] = max_anc + 1 + self.x_offset
             self._cond['ymax'] = self._cond['n_lines']
+
         # add horizontal lines
         for ii in range(n_fold + 1):
             feedline_r = (n_fold > 0 and n_fold > ii)
             feedline_l = (ii > 0)
             self._draw_regs_sub(ii, feedline_l, feedline_r)
-        # draw gate number
+
+        # draw anchor index number
         if self._style.index:
             for ii in range(max_anc):
                 if self.fold > 0:
-                    x_coord = ii % self.fold + 1
+                    x_coord = ii % self.fold + self._reg_long_text - 0.2
                     y_coord = - (ii // self.fold) * (self._cond['n_lines'] + 1) + 0.7
                 else:
-                    x_coord = ii + 1
+                    x_coord = ii + self._reg_long_text - 0.2
                     y_coord = 0.7
                 self.ax.text(x_coord, y_coord, str(ii + 1), ha='center',
-                             va='center', fontsize=self._scale * self._style.sfs,
-                             color=self._style.tc, clip_on=True,
-                             zorder=PORDER_TEXT)
-
-    @staticmethod
-    def param_parse(v):
-        # create an empty list to store the parameters in
-        param_parts = [None] * len(v)
-        for i, e in enumerate(v):
-            try:
-                param_parts[i] = pi_check(e, output='mpl', ndigits=3)
-            except TypeError:
-                param_parts[i] = str(e)
-
-            if param_parts[i].startswith('-'):
-                param_parts[i] = '$-$' + param_parts[i][1:]
-
-        param_parts = ', '.join(param_parts)
-        return param_parts
-
-    @staticmethod
-    def format_numeric(val, tol=1e-5):
-        if isinstance(val, complex):
-            return str(val)
-        elif complex(val).imag != 0:
-            val = complex(val)
-        abs_val = abs(val)
-        if math.isclose(abs_val, 0.0, abs_tol=1e-100):
-            return '0'
-        if math.isclose(math.fmod(abs_val, 1.0),
-                        0.0, abs_tol=tol) and 0.5 < abs_val < 9999.5:
-            return str(int(val))
-        if 0.1 <= abs_val < 100.0:
-            return '{:.2f}'.format(val)
-        return '{:.1e}'.format(val)
-
-    @staticmethod
-    def fraction(val, base=np.pi, n=100, tol=1e-5):
-        abs_val = abs(val)
-        for i in range(1, n):
-            for j in range(1, n):
-                if math.isclose(abs_val, i / j * base, rel_tol=tol):
-                    if val < 0:
-                        i *= -1
-                    return fractions.Fraction(i, j)
-        return None
+                             va='center', fontsize=self._style.sfs,
+                             color=self._style.tc, clip_on=True, zorder=PORDER_TEXT)
diff --git a/qiskit/visualization/qcstyle.py b/qiskit/visualization/qcstyle.py
--- a/qiskit/visualization/qcstyle.py
+++ b/qiskit/visualization/qcstyle.py
@@ -24,28 +24,27 @@ class DefaultStyle:
 
     def __init__(self):
         # Set colors
-        basis_color = '#FA74A6'
-        clifford_color = '#6FA4FF'
-        non_gate_color = '#000000'
-        other_color = '#BB8BFF'
-        pauli_color = '#05BAB6'
-        iden_color = '#05BAB6'
+        basis_color = '#FA74A6'     # Red
+        clifford_color = '#6FA4FF'  # Blue
+        non_gate_color = '#000000'  # Black
+        other_color = '#BB8BFF'     # Purple
+        pauli_color = '#05BAB6'     # Green
+        iden_color = '#05BAB6'      # Green
 
         self.name = 'iqx'
         self.tc = '#000000'
         self.sc = '#000000'
         self.lc = '#000000'
         self.not_gate_lc = '#ffffff'
-        self.cc = '#778899'
-        self.gc = '#ffffff'
+        self.cc = '#778899'         # Medium Gray
+        self.gc = other_color
         self.gt = '#000000'
-        self.bc = '#bdbdbd'
+        self.bc = '#bdbdbd'         # Dark Gray
         self.bg = '#ffffff'
         self.edge_color = None
         self.math_fs = 15
         self.fs = 13
         self.sfs = 8
-        self.colored_add_width = 0.2
         self.disptex = {
             'id': 'I',
             'u0': 'U_0',
@@ -60,11 +59,20 @@ def __init__(self):
             'sdg': 'S^\\dagger',
             't': 'T',
             'tdg': 'T^\\dagger',
+            'iswap': 'Iswap',
+            'dcx': 'Dcx',
+            'ms': 'MS',
+            'diagonal': 'Diagonal',
+            'unitary': 'Unitary',
             'r': 'R',
             'rx': 'R_x',
             'ry': 'R_y',
             'rz': 'R_z',
-            'reset': '\\left|0\\right\\rangle'
+            'rxx': 'R_{xx}',
+            'ryy': 'R_{yy}',
+            'rzx': 'R_{zx}',
+            'reset': '\\left|0\\right\\rangle',
+            'initialize': '|psi>'
         }
         self.dispcol = {
             'u0': basis_color,
@@ -90,13 +98,16 @@ def __init__(self):
             'rx': other_color,
             'ry': other_color,
             'rz': other_color,
+            'rxx': other_color,
+            'ryy': other_color,
+            'rzx': other_color,
             'reset': non_gate_color,
             'target': '#ffffff',
             'multi': other_color,
-            'meas': non_gate_color
+            'meas': non_gate_color,
+            'measure': non_gate_color
         }
         self.latexmode = False
-        self.bundle = True
         self.index = False
         self.figwidth = -1
         self.dpi = 150
@@ -118,7 +129,6 @@ def set_style(self, style_dic):
         self.disptex = dic.pop('displaytext', self.disptex)
         self.dispcol = dic.pop('displaycolor', self.dispcol)
         self.latexmode = dic.pop('latexdrawerstyle', self.latexmode)
-        self.bundle = dic.pop('cregbundle', self.bundle)
         self.index = dic.pop('showindex', self.index)
         self.figwidth = dic.pop('figwidth', self.figwidth)
         self.dpi = dic.pop('dpi', self.dpi)
@@ -145,7 +155,6 @@ def __init__(self):
         self.edge_color = '#000000'
         self.fs = 13
         self.math_fs = 15
-        self.colored_add_width = 0.2
         self.sfs = 8
         self.disptex = {
             'id': 'I',
@@ -161,43 +170,59 @@ def __init__(self):
             'sdg': 'S^\\dagger',
             't': 'T',
             'tdg': 'T^\\dagger',
+            'iswap': 'Iswap',
+            'dcx': 'Dcx',
+            'ms': 'MS',
+            'diagonal': 'Diagonal',
+            'unitary': 'Unitary',
             'r': 'R',
             'rx': 'R_x',
             'ry': 'R_y',
             'rz': 'R_z',
-            'reset': '\\left|0\\right\\rangle'
+            'rxx': 'R_{xx}',
+            'ryy': 'R_{yy}',
+            'rzx': 'R_{zx}',
+            'reset': '\\left|0\\right\\rangle',
+            'initialize': '|psi>'
         }
         self.dispcol = {
-            'id': '#ffffff',
             'u0': '#ffffff',
             'u1': '#ffffff',
             'u2': '#ffffff',
             'u3': '#ffffff',
+            'id': '#ffffff',
             'x': '#ffffff',
             'y': '#ffffff',
             'z': '#ffffff',
             'h': '#ffffff',
             'cx': '#000000',
+            'cy': '#ffffff',
+            'cz': '#000000',
+            'swap': '#000000',
             's': '#ffffff',
             'sdg': '#ffffff',
+            'dcx': '#ffffff',
+            'iswap': '#ffffff',
             't': '#ffffff',
             'tdg': '#ffffff',
             'r': '#ffffff',
             'rx': '#ffffff',
             'ry': '#ffffff',
             'rz': '#ffffff',
+            'rxx': '#ffffff',
+            'ryy': '#ffffff',
+            'rzx': '#ffffff',
             'reset': '#ffffff',
             'target': '#ffffff',
+            'multi': '#ffffff',
             'meas': '#ffffff',
-            'swap': '#000000',
-            'multi': '#000000'
+            'measure': '#ffffff'
         }
         self.latexmode = False
-        self.bundle = True
         self.index = False
         self.figwidth = -1
         self.dpi = 150
-        self.margin = [2.0, 0.0, 0.0, 0.3]
+        self.margin = [2.0, 0.1, 0.1, 0.3]
         self.cline = 'doublet'
 
     def set_style(self, style_dic):
@@ -217,7 +242,6 @@ def set_style(self, style_dic):
             self.dispcol[key] = self.gc
         self.dispcol = dic.pop('displaycolor', self.dispcol)
         self.latexmode = dic.pop('latexdrawerstyle', self.latexmode)
-        self.bundle = dic.pop('cregbundle', self.bundle)
         self.index = dic.pop('showindex', self.index)
         self.figwidth = dic.pop('figwidth', self.figwidth)
         self.dpi = dic.pop('dpi', self.dpi)


Test patch:
diff --git a/test/ipynb/mpl/references/big_gates.png b/test/ipynb/mpl/references/big_gates.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/big_gates.png differ
diff --git a/test/ipynb/mpl/references/cnot.png b/test/ipynb/mpl/references/cnot.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/cnot.png differ
diff --git a/test/ipynb/mpl/references/conditional.png b/test/ipynb/mpl/references/conditional.png
Binary files a/test/ipynb/mpl/references/conditional.png and b/test/ipynb/mpl/references/conditional.png differ
diff --git a/test/ipynb/mpl/references/creg_initial_false.png b/test/ipynb/mpl/references/creg_initial_false.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/creg_initial_false.png differ
diff --git a/test/ipynb/mpl/references/creg_initial_true.png b/test/ipynb/mpl/references/creg_initial_true.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/creg_initial_true.png differ
diff --git a/test/ipynb/mpl/references/cswap_rzz.png b/test/ipynb/mpl/references/cswap_rzz.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/cswap_rzz.png differ
diff --git a/test/ipynb/mpl/references/ctrl_labels.png b/test/ipynb/mpl/references/ctrl_labels.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/ctrl_labels.png differ
diff --git a/test/ipynb/mpl/references/fold_4.png b/test/ipynb/mpl/references/fold_4.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/fold_4.png differ
diff --git a/test/ipynb/mpl/references/fold_minus1.png b/test/ipynb/mpl/references/fold_minus1.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/fold_minus1.png differ
diff --git a/test/ipynb/mpl/references/ghz_to_gate.png b/test/ipynb/mpl/references/ghz_to_gate.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/ghz_to_gate.png differ
diff --git a/test/ipynb/mpl/references/long_name.png b/test/ipynb/mpl/references/long_name.png
Binary files a/test/ipynb/mpl/references/long_name.png and b/test/ipynb/mpl/references/long_name.png differ
diff --git a/test/ipynb/mpl/references/no_barriers.png b/test/ipynb/mpl/references/no_barriers.png
Binary files a/test/ipynb/mpl/references/no_barriers.png and b/test/ipynb/mpl/references/no_barriers.png differ
diff --git a/test/ipynb/mpl/references/pauli_clifford.png b/test/ipynb/mpl/references/pauli_clifford.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/pauli_clifford.png differ
diff --git a/test/ipynb/mpl/references/plot_barriers_false.png b/test/ipynb/mpl/references/plot_barriers_false.png
Binary files a/test/ipynb/mpl/references/plot_barriers_false.png and b/test/ipynb/mpl/references/plot_barriers_false.png differ
diff --git a/test/ipynb/mpl/references/plot_barriers_true.png b/test/ipynb/mpl/references/plot_barriers_true.png
Binary files a/test/ipynb/mpl/references/plot_barriers_true.png and b/test/ipynb/mpl/references/plot_barriers_true.png differ
diff --git a/test/ipynb/mpl/references/plot_partial_barrier.png b/test/ipynb/mpl/references/plot_partial_barrier.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/plot_partial_barrier.png differ
diff --git a/test/ipynb/mpl/references/r_gates.png b/test/ipynb/mpl/references/r_gates.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/r_gates.png differ
diff --git a/test/ipynb/mpl/references/u_gates.png b/test/ipynb/mpl/references/u_gates.png
new file mode 100644
Binary files /dev/null and b/test/ipynb/mpl/references/u_gates.png differ
diff --git a/test/ipynb/mpl/test_circuit_matplotlib_drawer.py b/test/ipynb/mpl/test_circuit_matplotlib_drawer.py
--- a/test/ipynb/mpl/test_circuit_matplotlib_drawer.py
+++ b/test/ipynb/mpl/test_circuit_matplotlib_drawer.py
@@ -17,12 +17,22 @@
 import json
 import os
 from contextlib import contextmanager
-
 from qiskit.test import QiskitTestCase
+
 from qiskit import QuantumCircuit, QuantumRegister, ClassicalRegister
 from qiskit.visualization.circuit_visualization import _matplotlib_circuit_drawer
+from qiskit.circuit.library import (U3Gate, U2Gate, U1Gate, XGate, SwapGate,
+                                    MCXGate, YGate, HGate, ZGate,
+                                    C4XGate, C3XGate, MSGate, RZZGate)
+from qiskit.extensions import HamiltonianGate, UnitaryGate
+from qiskit.circuit import Parameter
+from qiskit.circuit.library import IQP
 from qiskit.quantum_info.random import random_unitary
 
+import math
+import numpy as np
+from numpy import pi
+
 RESULTDIR = os.path.dirname(os.path.abspath(__file__))
 
 
@@ -103,6 +113,21 @@ def test_conditional(self):
 
         self.circuit_drawer(circuit, filename='conditional.png')
 
+    def test_plot_partial_barrier(self):
+        """Test plotting of partial barriers."""
+
+        # generate a circuit with barrier and other barrier like instructions in
+        q = QuantumRegister(2, 'q')
+        c = ClassicalRegister(2, 'c')
+        circuit = QuantumCircuit(q, c)
+
+        # check for barriers
+        circuit.h(q[0])
+        circuit.barrier(0)
+        circuit.h(q[0])
+
+        self.circuit_drawer(circuit, filename='plot_partial_barrier.png', plot_barriers=True)
+
     def test_plot_barriers(self):
         """Test to see that plotting barriers works.
         If it is set to False, no blank columns are introduced"""
@@ -138,6 +163,165 @@ def test_no_barriers_false(self):
 
         self.circuit_drawer(circuit, filename='no_barriers.png', plot_barriers=False)
 
+    def test_fold_minus1(self):
+        """Test to see that fold=-1 is no folding"""
+        qr = QuantumRegister(2, 'q')
+        cr = ClassicalRegister(1, 'c')
+        circuit = QuantumCircuit(qr, cr)
+        for _ in range(3):
+            circuit.h(0)
+            circuit.x(0)
+
+        self.circuit_drawer(circuit, fold=-1, filename='fold_minus1.png')
+
+    def test_fold_4(self):
+        """Test to see that fold=4 is folding"""
+        qr = QuantumRegister(2, 'q')
+        cr = ClassicalRegister(1, 'c')
+        circuit = QuantumCircuit(qr, cr)
+        for _ in range(3):
+            circuit.h(0)
+            circuit.x(0)
+
+        self.circuit_drawer(circuit, fold=4, filename='fold_4.png')
+
+    def test_big_gates(self):
+        """Test large gates with params"""
+        qr = QuantumRegister(6, 'q')
+        circuit = QuantumCircuit(qr)
+        A = [[6, 5, 3], [5, 4, 5], [3, 5, 1]]
+        circuit.append(IQP(A), [0, 1, 2])
+
+        desired_vector = [
+            1 / math.sqrt(16) * complex(0, 1),
+            1 / math.sqrt(8) * complex(1, 0),
+            1 / math.sqrt(16) * complex(1, 1),
+            0,
+            0,
+            1 / math.sqrt(8) * complex(1, 2),
+            1 / math.sqrt(16) * complex(1, 0),
+            0]
+
+        circuit.initialize(desired_vector, [qr[3], qr[4], qr[5]])
+        circuit.unitary([[1, 0], [0, 1]], [qr[0]])
+        matrix = np.zeros((4, 4))
+        theta = Parameter('theta')
+        circuit.append(HamiltonianGate(matrix, theta), [qr[1], qr[2]])
+        circuit = circuit.bind_parameters({theta: 1})
+        circuit.isometry(np.eye(4, 4), [i for i in range(3, 5)], [])
+
+        self.circuit_drawer(circuit, filename='big_gates.png')
+
+    def test_cnot(self):
+        """Test different cnot gates (ccnot, mcx, etc)"""
+        qr = QuantumRegister(5, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.x(0)
+        circuit.cx(0, 1)
+        circuit.ccx(0, 1, 2)
+        circuit.append(XGate().control(3, ctrl_state='010'), [qr[2], qr[3], qr[0], qr[1]])
+        circuit.append(MCXGate(num_ctrl_qubits=3, ctrl_state='101'), [qr[0], qr[1], qr[2], qr[4]])
+
+        self.circuit_drawer(circuit, filename='cnot.png')
+
+    def test_pauli_clifford(self):
+        """Test Pauli(green) and Clifford(blue) gates"""
+        qr = QuantumRegister(5, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.x(0)
+        circuit.y(0)
+        circuit.z(0)
+        circuit.id(0)
+        circuit.h(1)
+        circuit.cx(1, 2)
+        circuit.cy(1, 2)
+        circuit.cz(1, 2)
+        circuit.swap(3, 4)
+        circuit.s(3)
+        circuit.sdg(3)
+        circuit.iswap(3, 4)
+        circuit.dcx(3, 4)
+
+        self.circuit_drawer(circuit, filename='pauli_clifford.png')
+
+    def test_u_gates(self):
+        """Test U 1, 2, & 3 gates"""
+        qr = QuantumRegister(4, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.u1(3*pi/2, 0)
+        circuit.u2(3*pi/2, 2*pi/3, 1)
+        circuit.u3(3*pi/2, 4.5, pi/4, 2)
+        circuit.cu1(pi/4, 0, 1)
+        circuit.append(U2Gate(pi/2, 3*pi/2).control(1), [qr[2], qr[3]])
+        circuit.cu3(3*pi/2, -3*pi/4, -pi/2, 0, 1)
+
+        self.circuit_drawer(circuit, filename='u_gates.png')
+
+    def test_creg_initial(self):
+        """Test cregbundle and initial state options"""
+        qr = QuantumRegister(2, 'q')
+        cr = ClassicalRegister(2, 'c')
+        circuit = QuantumCircuit(qr, cr)
+        circuit.x(0)
+        circuit.h(0)
+        circuit.x(1)
+
+        self.circuit_drawer(circuit, filename='creg_initial_true.png',
+                            cregbundle=True, initial_state=True)
+        self.circuit_drawer(circuit, filename='creg_initial_false.png',
+                            cregbundle=False, initial_state=False)
+
+    def test_r_gates(self):
+        """Test all R gates"""
+        qr = QuantumRegister(4, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.r(3*pi/4, 3*pi/8, 0)
+        circuit.rx(pi/2, 1)
+        circuit.ry(-pi/2, 2)
+        circuit.rz(3*pi/4, 3)
+        circuit.rxx(pi/2, 0, 1)
+        circuit.ryy(3*pi/4, 2, 3)
+        circuit.rzx(-pi/2, 0, 1)
+        circuit.rzz(pi/2, 2, 3)
+
+        self.circuit_drawer(circuit, filename='r_gates.png')
+
+    def test_ctrl_labels(self):
+        """Test control labels"""
+        qr = QuantumRegister(4, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.cy(1, 0, label='Bottom Y Label')
+        circuit.cy(2, 3, label='Top Y Label')
+        circuit.ch(0, 1, label='Top H Label')
+        circuit.append(HGate(label='H Gate Label').control(3, label='H Control Label',
+                                                           ctrl_state='010'),
+                       [qr[1], qr[2], qr[3], qr[0]])
+
+        self.circuit_drawer(circuit, filename='ctrl_labels.png')
+
+    def test_cswap_rzz(self):
+        """Test controlled swap and rzz gates"""
+        qr = QuantumRegister(5, 'q')
+        circuit = QuantumCircuit(qr)
+        circuit.cswap(0, 1, 2)
+        circuit.append(RZZGate(3*pi/4).control(3, ctrl_state='010'), [2, 1, 4, 3, 0])
+
+        self.circuit_drawer(circuit, filename='cswap_rzz.png')
+
+    def test_ghz_to_gate(self):
+        """Test controlled GHZ to_gate circuit"""
+        qr = QuantumRegister(5, 'q')
+        circuit = QuantumCircuit(qr)
+        ghz_circuit = QuantumCircuit(3, name='This is a WWWWWWWWWWWide name Ctrl-GHZ Circuit')
+        ghz_circuit.h(0)
+        ghz_circuit.cx(0, 1)
+        ghz_circuit.cx(1, 2)
+        ghz = ghz_circuit.to_gate()
+        ccghz = ghz.control(2, ctrl_state='10')
+        circuit.append(ccghz, [4, 0, 1, 3, 2])
+
+        self.circuit_drawer(circuit, filename='ghz_to_gate.png')
+
     def test_scale(self):
         """Tests scale
         See: https://github.com/Qiskit/qiskit-terra/issues/4179"""
diff --git a/test/ipynb/results.py b/test/ipynb/results.py
--- a/test/ipynb/results.py
+++ b/test/ipynb/results.py
@@ -59,6 +59,8 @@ def black_or_b(diff_image, image, reference, opacity=0.85):
     new.paste(shade, mask=mask)
     if image.size != new.size:
         image = image.resize(new.size)
+    if image.size != thresholded_diff.size:
+        thresholded_diff = thresholded_diff.resize(image.size)
     new.paste(image, mask=thresholded_diff)
     return new
 
@@ -139,7 +141,7 @@ def summary(self):
             ret += '<div><a href="mpl/mismatch.zip">' \
                    'Download %s mismatch results as a zip</a></div>' % len(self.mismatch)
 
-        if len(self.mismatch) >= 2:
+        if len(self.missing) >= 2:
             zipfiles(self.missing, 'mpl/missing.zip')
             ret += '<div><a href="mpl/missing.zip">' \
                    'Download %s missing results as a zip</a></div>' % len(self.missing)
@@ -174,5 +176,5 @@ def _repr_html_(self):
     for file in os.listdir(os.path.join(SWD, 'mpl')):
         if file.endswith(".png") and not file.endswith(".diff.png"):
             result_files.append(file)
-    results = Results(result_files, 'mpl')
+    results = Results(sorted(result_files), 'mpl')
     results.diff_images()
diff --git a/test/python/visualization/references/matplotlib_barriers_ref.png b/test/python/visualization/references/matplotlib_barriers_ref.png
new file mode 100644
Binary files /dev/null and b/test/python/visualization/references/matplotlib_barriers_ref.png differ
diff --git a/test/python/visualization/references/matplotlib_conditional_ref.png b/test/python/visualization/references/matplotlib_conditional_ref.png
new file mode 100644
Binary files /dev/null and b/test/python/visualization/references/matplotlib_conditional_ref.png differ
diff --git a/test/python/visualization/test_visualization.py b/test/python/visualization/test_visualization.py
--- a/test/python/visualization/test_visualization.py
+++ b/test/python/visualization/test_visualization.py
@@ -120,7 +120,7 @@ def test_teleport(self):
         qc.x(qr[2]).c_if(cr, 2)
         qc.measure(qr[2], cr[2])
         try:
-            circuit_drawer(qc, filename=filename, output='latex_source')
+            circuit_drawer(qc, filename=filename, output='latex_source', cregbundle=False)
             self.assertNotEqual(os.path.exists(filename), False)
         finally:
             if os.path.exists(filename):