Repository: Qiskit/qiskit

Issue:
Latex drawer does not support controlled gates
### Information

- **Qiskit Terra version**: master
- **Python version**: 3.7
- **Operating system**: MacOS

### What is the current behavior?

The latex drawer does not print controlled gates correctly.

### Steps to reproduce the problem

```
qr = QuantumRegister(3, 'q')
circuit = QuantumCircuit(qr)
circuit.append(HGate().control(2), [qr[0], qr[1], qr[2]])
circuit.draw('latex')
```
![image](https://user-images.githubusercontent.com/766693/73392692-4bb03700-42a8-11ea-9509-597296b11c64.png)


### What is the expected behavior?

Something along the text drawer:
```
q_0: |0>──■──
          │  
q_1: |0>──■──
        ┌─┴─┐
q_2: |0>┤ H ├
        └───┘
```





Discussion:

Resolving patch:
diff --git a/qiskit/visualization/latex.py b/qiskit/visualization/latex.py
--- a/qiskit/visualization/latex.py
+++ b/qiskit/visualization/latex.py
@@ -12,7 +12,7 @@
 # copyright notice, and modified files need to carry a notice indicating
 # that they have been altered from the originals.
 
-# pylint: disable=invalid-name
+# pylint: disable=invalid-name,consider-using-enumerate
 
 """latex circuit visualization backends."""
 
@@ -23,6 +23,7 @@
 import re
 
 import numpy as np
+from qiskit.circuit.controlledgate import ControlledGate
 from qiskit.circuit.parameterexpression import ParameterExpression
 from qiskit.visualization import qcstyle as _qcstyle
 from qiskit.visualization import exceptions
@@ -242,6 +243,8 @@ def _get_image_depth(self):
                     self.has_box = True
                 if op.name in target_gates:
                     self.has_target = True
+                if isinstance(op.op, ControlledGate):
+                    self.has_target = True
 
         for layer in self.ops:
 
@@ -369,8 +372,74 @@ def _build_latex_array(self, aliases=None):
                     pos_2 = self.img_regs[cl_reg]
                     if_value = format(op.condition[1],
                                       'b').zfill(self.cregs[if_reg])[::-1]
-                if op.name not in ['measure', 'barrier', 'snapshot', 'load',
-                                   'save', 'noise']:
+                if isinstance(op.op, ControlledGate) and op.name not in [
+                        'ccx', 'cx', 'cz', 'cu1', 'ccz', 'cu3', 'crz',
+                        'cswap']:
+                    qarglist = op.qargs
+                    name = generate_latex_label(
+                        op.op.base_gate.name.upper()).replace(" ", "\\,")
+                    pos_array = []
+                    num_ctrl_qubits = op.op.num_ctrl_qubits
+                    num_qargs = len(qarglist) - num_ctrl_qubits
+                    for ctrl in range(len(qarglist)):
+                        pos_array.append(self.img_regs[qarglist[ctrl]])
+                    pos_qargs = pos_array[num_ctrl_qubits:]
+                    ctrl_pos = pos_array[:num_ctrl_qubits]
+                    if op.condition:
+                        mask = self._get_mask(op.condition[0])
+                        cl_reg = self.clbit_list[self._ffs(mask)]
+                        if_reg = cl_reg.register
+                        pos_cond = self.img_regs[if_reg[0]]
+                        temp = pos_array + [pos_cond]
+                        temp.sort(key=int)
+                        bottom = temp[len(pos_array) - 1]
+                        gap = pos_cond - bottom
+                        for i in range(self.cregs[if_reg]):
+                            if if_value[i] == '1':
+                                self._latex[pos_cond + i][column] = \
+                                    "\\control \\cw \\cwx[-" + str(gap) + "]"
+                                gap = 1
+                            else:
+                                self._latex[pos_cond + i][column] = \
+                                    "\\controlo \\cw \\cwx[-" + str(gap) + "]"
+                                gap = 1
+                    if num_qargs == 1:
+                        for index, pos in enumerate(ctrl_pos):
+                            self._latex[pos][column] = "\\ctrl{" + str(
+                                pos_array[index + 1] - pos_array[index]) + "}"
+                        self._latex[pos_array[-1]][column] = "\\gate{%s}" % name
+                    else:
+                        pos_start = min(pos_qargs)
+                        pos_stop = max(pos_qargs)
+                        # If any controls appear in the span of the multiqubit
+                        # gate just treat the whole thing as a big gate instead
+                        # of trying to render the controls separately
+                        if any(ctrl_pos) in range(pos_start, pos_stop):
+                            pos_start = min(pos_array)
+                            pos_stop = max(pos_array)
+                            num_qargs = len(qarglist)
+                            name = generate_latex_label(
+                                op.name).replace(" ", "\\,")
+                        else:
+                            for index, pos in enumerate(ctrl_pos):
+                                if index + 1 >= num_ctrl_qubits:
+                                    if pos_array[index] > pos_stop:
+                                        upper = pos_stop
+                                    else:
+                                        upper = pos_start
+                                else:
+                                    upper = pos_array[index + 1]
+
+                                self._latex[pos][column] = "\\ctrl{" + str(
+                                    upper - pos_array[index]) + "}"
+
+                        self._latex[pos_start][column] = ("\\multigate{%s}{%s}" %
+                                                          (num_qargs - 1, name))
+                        for pos in range(pos_start + 1, pos_stop + 1):
+                            self._latex[pos][column] = ("\\ghost{%s}" % name)
+
+                elif op.name not in ['measure', 'barrier', 'snapshot', 'load',
+                                     'save', 'noise']:
                     nm = generate_latex_label(op.name).replace(" ", "\\,")
                     qarglist = op.qargs
                     if aliases is not None:


Test patch: