|  | @@ -28,8 +28,8 @@ factory((root.pdfjsDistBuildPdfCombined = {}));
 | 
	
		
			
				|  |  |    // Use strict in our context only - users might not want it
 | 
	
		
			
				|  |  |    'use strict';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -var pdfjsVersion = '1.5.410';
 | 
	
		
			
				|  |  | -var pdfjsBuild = '61a576c';
 | 
	
		
			
				|  |  | +var pdfjsVersion = '1.5.413';
 | 
	
		
			
				|  |  | +var pdfjsBuild = '6bb95e3';
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    var pdfjsFilePath =
 | 
	
		
			
				|  |  |      typeof document !== 'undefined' && document.currentScript ?
 | 
	
	
		
			
				|  | @@ -24984,7 +24984,8 @@ var renderTextLayer = (function renderTextLayerClosure() {
 | 
	
		
			
				|  |  |      return !NonWhitespaceRegexp.test(str);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  function appendText(textDivs, viewport, geom, styles) {
 | 
	
		
			
				|  |  | +  function appendText(textDivs, viewport, geom, styles, bounds,
 | 
	
		
			
				|  |  | +                      enhanceTextSelection) {
 | 
	
		
			
				|  |  |      var style = styles[geom.fontName];
 | 
	
		
			
				|  |  |      var textDiv = document.createElement('div');
 | 
	
		
			
				|  |  |      textDivs.push(textDiv);
 | 
	
	
		
			
				|  | @@ -25040,6 +25041,34 @@ var renderTextLayer = (function renderTextLayerClosure() {
 | 
	
		
			
				|  |  |          textDiv.dataset.canvasWidth = geom.width * viewport.scale;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  | +    if (enhanceTextSelection) {
 | 
	
		
			
				|  |  | +      var angleCos = 1, angleSin = 0;
 | 
	
		
			
				|  |  | +      if (angle !== 0) {
 | 
	
		
			
				|  |  | +        angleCos = Math.cos(angle);
 | 
	
		
			
				|  |  | +        angleSin = Math.sin(angle);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      var divWidth = (style.vertical ? geom.height : geom.width) *
 | 
	
		
			
				|  |  | +                     viewport.scale;
 | 
	
		
			
				|  |  | +      var divHeight = fontHeight;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      var m, b;
 | 
	
		
			
				|  |  | +      if (angle !== 0) {
 | 
	
		
			
				|  |  | +        m = [angleCos, angleSin, -angleSin, angleCos, left, top];
 | 
	
		
			
				|  |  | +        b = Util.getAxialAlignedBoundingBox([0, 0, divWidth, divHeight], m);
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        b = [left, top, left + divWidth, top + divHeight];
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      bounds.push({
 | 
	
		
			
				|  |  | +        left: b[0],
 | 
	
		
			
				|  |  | +        top: b[1],
 | 
	
		
			
				|  |  | +        right: b[2],
 | 
	
		
			
				|  |  | +        bottom: b[3],
 | 
	
		
			
				|  |  | +        div: textDiv,
 | 
	
		
			
				|  |  | +        size: [divWidth, divHeight],
 | 
	
		
			
				|  |  | +        m: m
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    function render(task) {
 | 
	
	
		
			
				|  | @@ -25054,6 +25083,7 @@ var renderTextLayer = (function renderTextLayerClosure() {
 | 
	
		
			
				|  |  |      // No point in rendering many divs as it would make the browser
 | 
	
		
			
				|  |  |      // unusable even after the divs are rendered.
 | 
	
		
			
				|  |  |      if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {
 | 
	
		
			
				|  |  | +      task._renderingDone = true;
 | 
	
		
			
				|  |  |        capability.resolve();
 | 
	
		
			
				|  |  |        return;
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -25080,24 +25110,290 @@ var renderTextLayer = (function renderTextLayerClosure() {
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        var width = ctx.measureText(textDiv.textContent).width;
 | 
	
		
			
				|  |  | +      textDiv.dataset.originalWidth = width;
 | 
	
		
			
				|  |  |        textLayerFrag.appendChild(textDiv);
 | 
	
		
			
				|  |  | -      var transform;
 | 
	
		
			
				|  |  | -      if (textDiv.dataset.canvasWidth !== undefined && width > 0) {
 | 
	
		
			
				|  |  | -        // Dataset values come of type string.
 | 
	
		
			
				|  |  | -        var textScale = textDiv.dataset.canvasWidth / width;
 | 
	
		
			
				|  |  | -        transform = 'scaleX(' + textScale + ')';
 | 
	
		
			
				|  |  | -      } else {
 | 
	
		
			
				|  |  | -        transform = '';
 | 
	
		
			
				|  |  | +       var transform;
 | 
	
		
			
				|  |  | +       if (textDiv.dataset.canvasWidth !== undefined && width > 0) {
 | 
	
		
			
				|  |  | +        //  Dataset values come of type string.
 | 
	
		
			
				|  |  | +         var textScale = textDiv.dataset.canvasWidth / width;
 | 
	
		
			
				|  |  | +         transform = 'scaleX(' + textScale + ')';
 | 
	
		
			
				|  |  | +       } else {
 | 
	
		
			
				|  |  | +         transform = '';
 | 
	
		
			
				|  |  | +       }
 | 
	
		
			
				|  |  | +       var rotation = textDiv.dataset.angle;
 | 
	
		
			
				|  |  | +       if (rotation) {
 | 
	
		
			
				|  |  | +         transform = 'rotate(' + rotation + 'deg) ' + transform;
 | 
	
		
			
				|  |  | +       }
 | 
	
		
			
				|  |  | +       if (transform) {
 | 
	
		
			
				|  |  | +         textDiv.dataset.originalTransform = transform;
 | 
	
		
			
				|  |  | +         CustomStyle.setProp('transform' , textDiv, transform);
 | 
	
		
			
				|  |  | +       }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    task._renderingDone = true;
 | 
	
		
			
				|  |  | +    capability.resolve();
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  function expand(bounds, viewport) {
 | 
	
		
			
				|  |  | +    var expanded = expandBounds(viewport.width, viewport.height, bounds);
 | 
	
		
			
				|  |  | +    for (var i = 0; i < expanded.length; i++) {
 | 
	
		
			
				|  |  | +      var div = bounds[i].div;
 | 
	
		
			
				|  |  | +      if (!div.dataset.angle) {
 | 
	
		
			
				|  |  | +        div.dataset.paddingLeft = bounds[i].left - expanded[i].left;
 | 
	
		
			
				|  |  | +        div.dataset.paddingTop = bounds[i].top - expanded[i].top;
 | 
	
		
			
				|  |  | +        div.dataset.paddingRight = expanded[i].right - bounds[i].right;
 | 
	
		
			
				|  |  | +        div.dataset.paddingBottom = expanded[i].bottom - bounds[i].bottom;
 | 
	
		
			
				|  |  | +        continue;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      var rotation = textDiv.dataset.angle;
 | 
	
		
			
				|  |  | -      if (rotation) {
 | 
	
		
			
				|  |  | -        transform = 'rotate(' + rotation + 'deg) ' + transform;
 | 
	
		
			
				|  |  | +      // Box is rotated -- trying to find padding so rotated div will not
 | 
	
		
			
				|  |  | +      // exceed its expanded bounds.
 | 
	
		
			
				|  |  | +      var e = expanded[i], b = bounds[i];
 | 
	
		
			
				|  |  | +      var m = b.m, c = m[0], s = m[1];
 | 
	
		
			
				|  |  | +      // Finding intersections with expanded box.
 | 
	
		
			
				|  |  | +      var points = [[0, 0], [0, b.size[1]], [b.size[0], 0], b.size];
 | 
	
		
			
				|  |  | +      var ts = new Float64Array(64);
 | 
	
		
			
				|  |  | +      points.forEach(function (p, i) {
 | 
	
		
			
				|  |  | +        var t = Util.applyTransform(p, m);
 | 
	
		
			
				|  |  | +        ts[i + 0] = c && (e.left - t[0]) / c;
 | 
	
		
			
				|  |  | +        ts[i + 4] = s && (e.top - t[1]) / s;
 | 
	
		
			
				|  |  | +        ts[i + 8] = c && (e.right - t[0]) / c;
 | 
	
		
			
				|  |  | +        ts[i + 12] = s && (e.bottom - t[1]) / s;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        ts[i + 16] = s && (e.left - t[0]) / -s;
 | 
	
		
			
				|  |  | +        ts[i + 20] = c && (e.top - t[1]) / c;
 | 
	
		
			
				|  |  | +        ts[i + 24] = s && (e.right - t[0]) / -s;
 | 
	
		
			
				|  |  | +        ts[i + 28] = c && (e.bottom - t[1]) / c;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        ts[i + 32] = c && (e.left - t[0]) / -c;
 | 
	
		
			
				|  |  | +        ts[i + 36] = s && (e.top - t[1]) / -s;
 | 
	
		
			
				|  |  | +        ts[i + 40] = c && (e.right - t[0]) / -c;
 | 
	
		
			
				|  |  | +        ts[i + 44] = s && (e.bottom - t[1]) / -s;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        ts[i + 48] = s && (e.left - t[0]) / s;
 | 
	
		
			
				|  |  | +        ts[i + 52] = c && (e.top - t[1]) / -c;
 | 
	
		
			
				|  |  | +        ts[i + 56] = s && (e.right - t[0]) / s;
 | 
	
		
			
				|  |  | +        ts[i + 60] = c && (e.bottom - t[1]) / -c;
 | 
	
		
			
				|  |  | +      });
 | 
	
		
			
				|  |  | +      var findPositiveMin = function (ts, offset, count) {
 | 
	
		
			
				|  |  | +        var result = 0;
 | 
	
		
			
				|  |  | +          for (var i = 0; i < count; i++) {
 | 
	
		
			
				|  |  | +            var t = ts[offset++];
 | 
	
		
			
				|  |  | +            if (t > 0) {
 | 
	
		
			
				|  |  | +              result = result ? Math.min(t, result) : t;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          return result;
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  | +      // Not based on math, but to simplify calculations, using cos and sin
 | 
	
		
			
				|  |  | +      // absolute values to not exceed the box (it can but insignificantly).
 | 
	
		
			
				|  |  | +      var boxScale = 1 + Math.min(Math.abs(c), Math.abs(s));
 | 
	
		
			
				|  |  | +      div.dataset.paddingLeft = findPositiveMin(ts, 32, 16) / boxScale;
 | 
	
		
			
				|  |  | +      div.dataset.paddingTop = findPositiveMin(ts, 48, 16) / boxScale;
 | 
	
		
			
				|  |  | +      div.dataset.paddingRight = findPositiveMin(ts, 0, 16) / boxScale;
 | 
	
		
			
				|  |  | +      div.dataset.paddingBottom = findPositiveMin(ts, 16, 16) / boxScale;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  function expandBounds(width, height, boxes) {
 | 
	
		
			
				|  |  | +    var bounds = boxes.map(function (box, i) {
 | 
	
		
			
				|  |  | +      return {
 | 
	
		
			
				|  |  | +        x1: box.left,
 | 
	
		
			
				|  |  | +        y1: box.top,
 | 
	
		
			
				|  |  | +        x2: box.right,
 | 
	
		
			
				|  |  | +        y2: box.bottom,
 | 
	
		
			
				|  |  | +        index: i,
 | 
	
		
			
				|  |  | +        x1New: undefined,
 | 
	
		
			
				|  |  | +        x2New: undefined
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    expandBoundsLTR(width, bounds);
 | 
	
		
			
				|  |  | +    var expanded = new Array(boxes.length);
 | 
	
		
			
				|  |  | +    bounds.forEach(function (b) {
 | 
	
		
			
				|  |  | +      var i = b.index;
 | 
	
		
			
				|  |  | +      expanded[i] = {
 | 
	
		
			
				|  |  | +        left: b.x1New,
 | 
	
		
			
				|  |  | +        top: 0,
 | 
	
		
			
				|  |  | +        right: b.x2New,
 | 
	
		
			
				|  |  | +        bottom: 0
 | 
	
		
			
				|  |  | +      };
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Rotating on 90 degrees and extending extended boxes. Reusing the bounds
 | 
	
		
			
				|  |  | +    // array and objects.
 | 
	
		
			
				|  |  | +    boxes.map(function (box, i) {
 | 
	
		
			
				|  |  | +      var e = expanded[i], b = bounds[i];
 | 
	
		
			
				|  |  | +      b.x1 = box.top;
 | 
	
		
			
				|  |  | +      b.y1 = width - e.right;
 | 
	
		
			
				|  |  | +      b.x2 = box.bottom;
 | 
	
		
			
				|  |  | +      b.y2 = width - e.left;
 | 
	
		
			
				|  |  | +      b.index = i;
 | 
	
		
			
				|  |  | +      b.x1New = undefined;
 | 
	
		
			
				|  |  | +      b.x2New = undefined;
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    expandBoundsLTR(height, bounds);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    bounds.forEach(function (b) {
 | 
	
		
			
				|  |  | +      var i = b.index;
 | 
	
		
			
				|  |  | +      expanded[i].top = b.x1New;
 | 
	
		
			
				|  |  | +      expanded[i].bottom = b.x2New;
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +    return expanded;
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  function expandBoundsLTR(width, bounds) {
 | 
	
		
			
				|  |  | +    // Sorting by x1 coordinate and walk by the bounds in the same order.
 | 
	
		
			
				|  |  | +    bounds.sort(function (a, b) { return a.x1 - b.x1 || a.index - b.index; });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // First we see on the horizon is a fake boundary.
 | 
	
		
			
				|  |  | +    var fakeBoundary = {
 | 
	
		
			
				|  |  | +      x1: -Infinity,
 | 
	
		
			
				|  |  | +      y1: -Infinity,
 | 
	
		
			
				|  |  | +      x2: 0,
 | 
	
		
			
				|  |  | +      y2: Infinity,
 | 
	
		
			
				|  |  | +      index: -1,
 | 
	
		
			
				|  |  | +      x1New: 0,
 | 
	
		
			
				|  |  | +      x2New: 0
 | 
	
		
			
				|  |  | +    };
 | 
	
		
			
				|  |  | +    var horizon = [{
 | 
	
		
			
				|  |  | +      start: -Infinity,
 | 
	
		
			
				|  |  | +      end: Infinity,
 | 
	
		
			
				|  |  | +      boundary: fakeBoundary
 | 
	
		
			
				|  |  | +    }];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    bounds.forEach(function (boundary) {
 | 
	
		
			
				|  |  | +      // Searching for the affected part of horizon.
 | 
	
		
			
				|  |  | +      // TODO red-black tree or simple binary search
 | 
	
		
			
				|  |  | +      var i = 0;
 | 
	
		
			
				|  |  | +      while (i < horizon.length && horizon[i].end <= boundary.y1) {
 | 
	
		
			
				|  |  | +        i++;
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -      if (transform) {
 | 
	
		
			
				|  |  | -        CustomStyle.setProp('transform' , textDiv, transform);
 | 
	
		
			
				|  |  | +      var j = horizon.length - 1;
 | 
	
		
			
				|  |  | +      while(j >= 0 && horizon[j].start >= boundary.y2) {
 | 
	
		
			
				|  |  | +        j--;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      var horizonPart, affectedBoundary;
 | 
	
		
			
				|  |  | +      var q, k, maxXNew = -Infinity;
 | 
	
		
			
				|  |  | +      for (q = i; q <= j; q++) {
 | 
	
		
			
				|  |  | +        horizonPart = horizon[q];
 | 
	
		
			
				|  |  | +        affectedBoundary = horizonPart.boundary;
 | 
	
		
			
				|  |  | +        var xNew;
 | 
	
		
			
				|  |  | +        if (affectedBoundary.x2 > boundary.x1) {
 | 
	
		
			
				|  |  | +          // In the middle of the previous element, new x shall be at the
 | 
	
		
			
				|  |  | +          // boundary start. Extending if further if the affected bondary
 | 
	
		
			
				|  |  | +          // placed on top of the current one.
 | 
	
		
			
				|  |  | +          xNew = affectedBoundary.index > boundary.index ?
 | 
	
		
			
				|  |  | +            affectedBoundary.x1New : boundary.x1;
 | 
	
		
			
				|  |  | +        } else if (affectedBoundary.x2New === undefined) {
 | 
	
		
			
				|  |  | +          // We have some space in between, new x in middle will be a fair
 | 
	
		
			
				|  |  | +          // choice.
 | 
	
		
			
				|  |  | +          xNew = (affectedBoundary.x2 + boundary.x1) / 2;
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +          // Affected boundary has x2new set, using it as new x.
 | 
	
		
			
				|  |  | +          xNew = affectedBoundary.x2New;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (xNew > maxXNew) {
 | 
	
		
			
				|  |  | +          maxXNew = xNew;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    capability.resolve();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Set new x1 for current boundary.
 | 
	
		
			
				|  |  | +      boundary.x1New = maxXNew;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Adjusts new x2 for the affected boundaries.
 | 
	
		
			
				|  |  | +      for (q = i; q <= j; q++) {
 | 
	
		
			
				|  |  | +        horizonPart = horizon[q];
 | 
	
		
			
				|  |  | +        affectedBoundary = horizonPart.boundary;
 | 
	
		
			
				|  |  | +        if (affectedBoundary.x2New === undefined) {
 | 
	
		
			
				|  |  | +          // Was not set yet, choosing new x if possible.
 | 
	
		
			
				|  |  | +          if (affectedBoundary.x2 > boundary.x1) {
 | 
	
		
			
				|  |  | +            // Current and affected boundaries intersect. If affected boundary
 | 
	
		
			
				|  |  | +            // is placed on top of the current, shrinking the affected.
 | 
	
		
			
				|  |  | +            if (affectedBoundary.index > boundary.index) {
 | 
	
		
			
				|  |  | +              affectedBoundary.x2New = affectedBoundary.x2;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +          } else {
 | 
	
		
			
				|  |  | +            affectedBoundary.x2New = maxXNew;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        } else if (affectedBoundary.x2New > maxXNew) {
 | 
	
		
			
				|  |  | +          // Affected boundary is touching new x, pushing it back.
 | 
	
		
			
				|  |  | +          affectedBoundary.x2New = Math.max(maxXNew, affectedBoundary.x2);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Fixing the horizon.
 | 
	
		
			
				|  |  | +      var changedHorizon = [], lastBoundary = null;
 | 
	
		
			
				|  |  | +      for (q = i; q <= j; q++) {
 | 
	
		
			
				|  |  | +        horizonPart = horizon[q];
 | 
	
		
			
				|  |  | +        affectedBoundary = horizonPart.boundary;
 | 
	
		
			
				|  |  | +        // Checking which boundary will be visible.
 | 
	
		
			
				|  |  | +        var useBoundary = affectedBoundary.x2 > boundary.x2 ?
 | 
	
		
			
				|  |  | +          affectedBoundary : boundary;
 | 
	
		
			
				|  |  | +        if (lastBoundary === useBoundary) {
 | 
	
		
			
				|  |  | +          // Merging with previous.
 | 
	
		
			
				|  |  | +          changedHorizon[changedHorizon.length - 1].end = horizonPart.end;
 | 
	
		
			
				|  |  | +        } else {
 | 
	
		
			
				|  |  | +          changedHorizon.push({
 | 
	
		
			
				|  |  | +            start: horizonPart.start,
 | 
	
		
			
				|  |  | +            end: horizonPart.end,
 | 
	
		
			
				|  |  | +            boundary: useBoundary
 | 
	
		
			
				|  |  | +          });
 | 
	
		
			
				|  |  | +          lastBoundary = useBoundary;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (horizon[i].start < boundary.y1) {
 | 
	
		
			
				|  |  | +        changedHorizon[0].start = boundary.y1;
 | 
	
		
			
				|  |  | +        changedHorizon.unshift({
 | 
	
		
			
				|  |  | +          start: horizon[i].start,
 | 
	
		
			
				|  |  | +          end: boundary.y1,
 | 
	
		
			
				|  |  | +          boundary: horizon[i].boundary
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (boundary.y2 < horizon[j].end) {
 | 
	
		
			
				|  |  | +        changedHorizon[changedHorizon.length - 1].end = boundary.y2;
 | 
	
		
			
				|  |  | +        changedHorizon.push({
 | 
	
		
			
				|  |  | +          start: boundary.y2,
 | 
	
		
			
				|  |  | +          end: horizon[j].end,
 | 
	
		
			
				|  |  | +          boundary: horizon[j].boundary
 | 
	
		
			
				|  |  | +        });
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      // Set x2 new of boundary that is no longer visible (see overlapping case
 | 
	
		
			
				|  |  | +      // above).
 | 
	
		
			
				|  |  | +      // TODO more efficient, e.g. via reference counting.
 | 
	
		
			
				|  |  | +      for (q = i; q <= j; q++) {
 | 
	
		
			
				|  |  | +        horizonPart = horizon[q];
 | 
	
		
			
				|  |  | +        affectedBoundary = horizonPart.boundary;
 | 
	
		
			
				|  |  | +        if (affectedBoundary.x2New !== undefined) {
 | 
	
		
			
				|  |  | +          continue;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        var used = false;
 | 
	
		
			
				|  |  | +        for (k = i - 1; !used && k >= 0 &&
 | 
	
		
			
				|  |  | +        horizon[k].start >= affectedBoundary.y1; k--) {
 | 
	
		
			
				|  |  | +          used = horizon[k].boundary === affectedBoundary;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        for (k = j + 1; !used && k < horizon.length &&
 | 
	
		
			
				|  |  | +        horizon[k].end <= affectedBoundary.y2; k++) {
 | 
	
		
			
				|  |  | +          used = horizon[k].boundary === affectedBoundary;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        for (k = 0; !used && k < changedHorizon.length; k++) {
 | 
	
		
			
				|  |  | +          used = changedHorizon[k].boundary === affectedBoundary;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        if (!used) {
 | 
	
		
			
				|  |  | +          affectedBoundary.x2New = maxXNew;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +      Array.prototype.splice.apply(horizon,
 | 
	
		
			
				|  |  | +        [i, j - i + 1].concat(changedHorizon));
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    // Set new x2 for all unset boundaries.
 | 
	
		
			
				|  |  | +    horizon.forEach(function (horizonPart) {
 | 
	
		
			
				|  |  | +      var affectedBoundary = horizonPart.boundary;
 | 
	
		
			
				|  |  | +      if (affectedBoundary.x2New === undefined) {
 | 
	
		
			
				|  |  | +        affectedBoundary.x2New = Math.max(width, affectedBoundary.x2);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    });
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    /**
 | 
	
	
		
			
				|  | @@ -25107,17 +25403,23 @@ var renderTextLayer = (function renderTextLayerClosure() {
 | 
	
		
			
				|  |  |     * @param {HTMLElement} container
 | 
	
		
			
				|  |  |     * @param {PageViewport} viewport
 | 
	
		
			
				|  |  |     * @param {Array} textDivs
 | 
	
		
			
				|  |  | +   * @param {boolean} enhanceTextSelection
 | 
	
		
			
				|  |  |     * @private
 | 
	
		
			
				|  |  |     */
 | 
	
		
			
				|  |  | -  function TextLayerRenderTask(textContent, container, viewport, textDivs) {
 | 
	
		
			
				|  |  | +  function TextLayerRenderTask(textContent, container, viewport, textDivs,
 | 
	
		
			
				|  |  | +                               enhanceTextSelection) {
 | 
	
		
			
				|  |  |      this._textContent = textContent;
 | 
	
		
			
				|  |  |      this._container = container;
 | 
	
		
			
				|  |  |      this._viewport = viewport;
 | 
	
		
			
				|  |  |      textDivs = textDivs || [];
 | 
	
		
			
				|  |  |      this._textDivs = textDivs;
 | 
	
		
			
				|  |  | +    this._renderingDone = false;
 | 
	
		
			
				|  |  |      this._canceled = false;
 | 
	
		
			
				|  |  |      this._capability = createPromiseCapability();
 | 
	
		
			
				|  |  |      this._renderTimer = null;
 | 
	
		
			
				|  |  | +    this._bounds = [];
 | 
	
		
			
				|  |  | +    this._enhanceTextSelection = !!enhanceTextSelection;
 | 
	
		
			
				|  |  | +    this._expanded = false;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    TextLayerRenderTask.prototype = {
 | 
	
		
			
				|  |  |      get promise() {
 | 
	
	
		
			
				|  | @@ -25138,8 +25440,11 @@ var renderTextLayer = (function renderTextLayerClosure() {
 | 
	
		
			
				|  |  |        var styles = this._textContent.styles;
 | 
	
		
			
				|  |  |        var textDivs = this._textDivs;
 | 
	
		
			
				|  |  |        var viewport = this._viewport;
 | 
	
		
			
				|  |  | +      var enhanceTextSelection = this._enhanceTextSelection;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |        for (var i = 0, len = textItems.length; i < len; i++) {
 | 
	
		
			
				|  |  | -        appendText(textDivs, viewport, textItems[i], styles);
 | 
	
		
			
				|  |  | +        appendText(textDivs, viewport, textItems[i], styles, this._bounds,
 | 
	
		
			
				|  |  | +                   enhanceTextSelection);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |        if (!timeout) { // Render right away
 | 
	
	
		
			
				|  | @@ -25151,7 +25456,63 @@ var renderTextLayer = (function renderTextLayerClosure() {
 | 
	
		
			
				|  |  |            self._renderTimer = null;
 | 
	
		
			
				|  |  |          }, timeout);
 | 
	
		
			
				|  |  |        }
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +    expandTextDivs: function TextLayer_expandTextDivs(expandDivs) {
 | 
	
		
			
				|  |  | +      if (!this._enhanceTextSelection || !this._renderingDone) {
 | 
	
		
			
				|  |  | +        return;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (!this._expanded) {
 | 
	
		
			
				|  |  | +        expand(this._bounds, this._viewport);
 | 
	
		
			
				|  |  | +        this._expanded = true;
 | 
	
		
			
				|  |  | +        this._bounds.length = 0;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      if (expandDivs) {
 | 
	
		
			
				|  |  | +        for (var i = 0, ii = this._textDivs.length; i < ii; i++) {
 | 
	
		
			
				|  |  | +          var div = this._textDivs[i];
 | 
	
		
			
				|  |  | +          var transform;
 | 
	
		
			
				|  |  | +          var width = div.dataset.originalWidth;
 | 
	
		
			
				|  |  | +          if (div.dataset.canvasWidth !== undefined && width > 0) {
 | 
	
		
			
				|  |  | +            // Dataset values come of type string.
 | 
	
		
			
				|  |  | +            var textScale = div.dataset.canvasWidth / width;
 | 
	
		
			
				|  |  | +            transform = 'scaleX(' + textScale + ')';
 | 
	
		
			
				|  |  | +          } else {
 | 
	
		
			
				|  |  | +            transform = '';
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          var rotation = div.dataset.angle;
 | 
	
		
			
				|  |  | +          if (rotation) {
 | 
	
		
			
				|  |  | +            transform = 'rotate(' + rotation + 'deg) ' + transform;
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          if (div.dataset.paddingLeft) {
 | 
	
		
			
				|  |  | +            div.style.paddingLeft =
 | 
	
		
			
				|  |  | +              (div.dataset.paddingLeft / textScale) + 'px';
 | 
	
		
			
				|  |  | +            transform += ' translateX(' +
 | 
	
		
			
				|  |  | +              (-div.dataset.paddingLeft / textScale) + 'px)';
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          if (div.dataset.paddingTop) {
 | 
	
		
			
				|  |  | +            div.style.paddingTop = div.dataset.paddingTop + 'px';
 | 
	
		
			
				|  |  | +            transform += ' translateY(' + (-div.dataset.paddingTop) + 'px)';
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          if (div.dataset.paddingRight) {
 | 
	
		
			
				|  |  | +            div.style.paddingRight =
 | 
	
		
			
				|  |  | +            div.dataset.paddingRight / textScale + 'px';
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          if (div.dataset.paddingBottom) {
 | 
	
		
			
				|  |  | +            div.style.paddingBottom = div.dataset.paddingBottom + 'px';
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +          if (transform) {
 | 
	
		
			
				|  |  | +            CustomStyle.setProp('transform' , div, transform);
 | 
	
		
			
				|  |  | +          }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        for (i = 0, ii = this._textDivs.length; i < ii; i++) {
 | 
	
		
			
				|  |  | +          div = this._textDivs[i];
 | 
	
		
			
				|  |  | +          div.style.padding = 0;
 | 
	
		
			
				|  |  | +          transform = div.dataset.originalTransform || '';
 | 
	
		
			
				|  |  | +          CustomStyle.setProp('transform', div, transform);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    },
 | 
	
		
			
				|  |  |    };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -25165,7 +25526,8 @@ var renderTextLayer = (function renderTextLayerClosure() {
 | 
	
		
			
				|  |  |      var task = new TextLayerRenderTask(renderParameters.textContent,
 | 
	
		
			
				|  |  |                                         renderParameters.container,
 | 
	
		
			
				|  |  |                                         renderParameters.viewport,
 | 
	
		
			
				|  |  | -                                       renderParameters.textDivs);
 | 
	
		
			
				|  |  | +                                       renderParameters.textDivs,
 | 
	
		
			
				|  |  | +                                       renderParameters.enhanceTextSelection);
 | 
	
		
			
				|  |  |      task._render(renderParameters.timeout);
 | 
	
		
			
				|  |  |      return task;
 | 
	
		
			
				|  |  |    }
 |