code: def compile(self, ttFont):
      # First make sure that all the data lines up properly. Format 4
      # must have all its data lined up consecutively. If not this will fail.
      for curLoc, nxtLoc in zip(self.locations, self.locations[1:]):
          assert (
              curLoc[1] == nxtLoc[0]
          ), "Data must be consecutive in indexSubTable format 4"
  
      offsets = list(self.locations[0]) + [
          loc[1] for loc in self.locations[1:]
      ]
      # Image data offset must be less than or equal to the minimum of locations.
      # Resetting this offset may change the value for round tripping but is safer
      # and allows imageDataOffset to not be required to be in the XML version.
      self.imageDataOffset = min(offsets)
      offsets = [offset - self.imageDataOffset for offset in offsets]
      glyphIds = list(map(ttFont.getGlyphID, self.names))
      # Create an iterator over the ids plus a padding value.
      idsPlusPad = list(itertools.chain(glyphIds, [0]))
  
      dataList = [EblcIndexSubTable.compile(self, ttFont)]
      dataList.append(struct.pack(">L", len(glyphIds)))
      tmp = [
          struct.pack(codeOffsetPairFormat, *cop)
          for cop in zip(idsPlusPad, offsets)
      ]
      dataList += tmp
      data = bytesjoin(dataList)
      return data
  
imports: from fontTools.misc import sstruct
  from .None import DefaultTable
  from fontTools.misc.textTools import bytesjoin, safeEval
  from .BitmapGlyphMetrics import BigGlyphMetrics, bigGlyphMetricsFormat, SmallGlyphMetrics, smallGlyphMetricsFormat
  import struct
  import itertools
  from collections import deque
  import logging
label_desc: Use image node_id 2 for calling the eblc_index_sub_table_4 obj's underlying member method code with example usage: obj.compile(ttFont) and returns: data