text: export default {
    annotate(x, y, w, h, options) {
      options.Type = 'Annot';
      options.Rect = this._convertRect(x, y, w, h);
      options.Border = [0, 0, 0];
  
      if (options.Subtype !== 'Link') { if (options.C == null) { options.C = this._normalizeColor(options.color || [0, 0, 0]); } } // convert colors
      delete options.color;
  
      if (typeof options.Dest === 'string') {
        options.Dest = new String(options.Dest);
      }
  
      // Capitalize keys
      for (let key in options) {
        const val = options[key];
        options[key[0].toUpperCase() + key.slice(1)] = val;
      }
  
      const ref = this.ref(options);
      this.page.annotations.push(ref);
      ref.end();
      return this;
    },
  
    note(x, y, w, h, contents, options) {
      if (options == null) { options = {}; }
      options.Subtype = 'Text';
      options.Contents = new String(contents);
      options.Name = 'Comment';
      if (options.color == null) { options.color = [243, 223, 92]; }
      return this.annotate(x, y, w, h, options);
    },
  
    link(x, y, w, h, url, options) {
      if (options == null) { options = {}; }
      options.Subtype = 'Link';
  
      if (typeof url === 'number') {
        // Link to a page in the document (the page must already exist)
        const pages = this._root.data.Pages.data;
  
        if ((url >= 0) && (url < pages.Kids.length)) {
          options.A = this.ref({
            S: 'GoTo',
            D: [pages.Kids[url], 'XYZ', null, null, null]});
          options.A.end();
        } else {
          throw new Error(`The document has no page ${url}`);
        }
      } else {
        // Link to an external url
        options.A = this.ref({
          S: 'URI',
          URI: new String(url)
        });
        options.A.end();
      }
  
      return this.annotate(x, y, w, h, options);
    },
  
    _markup(x, y, w, h, options) {
      if (options == null) { options = {}; }
      const [x1, y1, x2, y2] = this._convertRect(x, y, w, h);
      options.QuadPoints = [x1, y2, x2, y2, x1, y1, x2, y1];
      options.Contents = new String;
      return this.annotate(x, y, w, h, options);
    },
  
    highlight(x, y, w, h, options) {
      if (options == null) { options = {}; }
      options.Subtype = 'Highlight';
      if (options.color == null) { options.color = [241, 238, 148]; }
      return this._markup(x, y, w, h, options);
    },
  
    underline(x, y, w, h, options) {
      if (options == null) { options = {}; }
      options.Subtype = 'Underline';
      return this._markup(x, y, w, h, options);
    },
  
    strike(x, y, w, h, options) {
      if (options == null) { options = {}; }
      options.Subtype = 'StrikeOut';
      return this._markup(x, y, w, h, options);
    },
  
    lineAnnotation(x1, y1, x2, y2, options) {
      if (options == null) { options = {}; }
      options.Subtype = 'Line';
      options.Contents = new String;
      options.L = [x1, this.page.height - y1, x2, this.page.height - y2];
      return this.annotate(x1, y1, x2, y2, options);
    },
  
    rectAnnotation(x, y, w, h, options) {
      if (options == null) { options = {}; }
      options.Subtype = 'Square';
      options.Contents = new String;
      return this.annotate(x, y, w, h, options);
    },
  
    ellipseAnnotation(x, y, w, h, options) {
      if (options == null) { options = {}; }
      options.Subtype = 'Circle';
      options.Contents = new String;
      return this.annotate(x, y, w, h, options);
    },
  
    textAnnotation(x, y, w, h, text, options) {
      if (options == null) { options = {}; }
      options.Subtype = 'FreeText';
      options.Contents = new String(text);
      options.DA = new String;
      return this.annotate(x, y, w, h, options);
    },
  
    _convertRect(x1, y1, w, h) {
      // flip y1 and y2
      let y2 = y1;
      y1 += h;
  
      // make x2
      let x2 = x1 + w;
  
      // apply current transformation matrix to points
      const [m0, m1, m2, m3, m4, m5] = this._ctm;
      x1 = (m0 * x1) + (m2 * y1) + m4;
      y1 = (m1 * x1) + (m3 * y1) + m5;
      x2 = (m0 * x2) + (m2 * y2) + m4;
      y2 = (m1 * x2) + (m3 * y2) + m5;
  
      return [x1, y1, x2, y2];
    }
  };
  