code: private function readTextObject()
      {
          $length = self::getUInt2d($this->data, $this->pos + 2);
          $recordData = $this->readRecordData($this->data, $this->pos + 4, $length);
  
          // move stream pointer to next record
          $this->pos += 4 + $length;
  
          if ($this->readDataOnly) {
              return;
          }
  
          // recordData consists of an array of subrecords looking like this:
          //    grbit: 2 bytes; Option Flags
          //    rot: 2 bytes; rotation
          //    cchText: 2 bytes; length of the text (in the first continue record)
          //    cbRuns: 2 bytes; length of the formatting (in the second continue record)
          // followed by the continuation records containing the actual text and formatting
          $grbitOpts = self::getUInt2d($recordData, 0);
          $rot = self::getUInt2d($recordData, 2);
          $cchText = self::getUInt2d($recordData, 10);
          $cbRuns = self::getUInt2d($recordData, 12);
          $text = $this->getSplicedRecordData();
  
          $textByte = $text['spliceOffsets'][1] - $text['spliceOffsets'][0] - 1;
          $textStr = substr($text['recordData'], $text['spliceOffsets'][0] + 1, $textByte);
          // get 1 byte
          $is16Bit = ord($text['recordData'][0]);
          // it is possible to use a compressed format,
          // which omits the high bytes of all characters, if they are all zero
          if (($is16Bit & 0x01) === 0) {
              $textStr = StringHelper::ConvertEncoding($textStr, 'UTF-8', 'ISO-8859-1');
          } else {
              $textStr = $this->decodeCodepage($textStr);
          }
  
          $this->textObjects[$this->textObjRef] = [
              'text' => $textStr,
              'format' => substr($text['recordData'], $text['spliceOffsets'][1], $cbRuns),
              'alignment' => $grbitOpts,
              'rotation' => $rot,
          ];
      }
docs: The TEXT Object record contains the text associated with a cell annotation.