Ignore:
Timestamp:
Apr 8, 2010, 10:16:54 AM (11 years ago)
Author:
dmik
Message:

Merged bramches/kmk (r294:365) to trunk.

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/poppler/mypoppler/poppler/TextOutputDev.cc

    r277 r367  
    16161616}
    16171617
     1618GBool TextBlock::isBeforeByRule1(TextBlock *blk1) {
     1619  GBool before = gFalse;
     1620  GBool overlap = gFalse;
     1621
     1622  switch (this->page->primaryRot) {
     1623  case 0:
     1624  case 2:
     1625    overlap = ((this->xMin <= blk1->xMin) &&
     1626               (blk1->xMin <= this->xMax)) ||
     1627      ((blk1->xMin <= this->xMin) &&
     1628       (this->xMin <= blk1->xMax));
     1629    break;
     1630  case 1:
     1631  case 3:
     1632    overlap = ((this->yMin <= blk1->yMin) &&
     1633               (blk1->yMin <= this->yMax)) ||
     1634      ((blk1->yMin <= this->yMin) &&
     1635       (this->yMin <= blk1->yMax));
     1636    break;
     1637  }
     1638  switch (this->page->primaryRot) {
     1639  case 0:
     1640    before = overlap && this->yMin < blk1->yMin;
     1641    break;
     1642  case 1:
     1643    before = overlap && this->xMax > blk1->xMax;
     1644    break;
     1645  case 2:
     1646    before = overlap && this->yMax > blk1->yMax;
     1647    break;
     1648  case 3:
     1649    before = overlap && this->xMin < blk1->xMin;
     1650    break;
     1651  }
     1652  return before;
     1653}
     1654
     1655GBool TextBlock::isBeforeByRule2(TextBlock *blk1) {
     1656  double cmp = 0;
     1657  int rotLR = rot;
     1658
     1659  if (!page->primaryLR) {
     1660    rotLR = (rotLR + 2) % 4;
     1661  }
     1662
     1663  switch (rotLR) {
     1664  case 0:
     1665    cmp = xMax - blk1->xMin;
     1666    break;
     1667  case 1:
     1668    cmp = yMin - blk1->yMax;
     1669    break;
     1670  case 2:
     1671    cmp = blk1->xMax - xMin;
     1672    break;
     1673  case 3:
     1674    cmp = blk1->yMin - yMax;
     1675    break;
     1676  }
     1677  return cmp <= 0;
     1678}
     1679
     1680// Sort into reading order by performing a topological sort using the rules
     1681// given in "High Performance Document Layout Analysis", T.M. Breuel, 2003.
     1682// See http://pubs.iupr.org/#2003-breuel-sdiut
     1683// Topological sort is done by depth first search, see
     1684// http://en.wikipedia.org/wiki/Topological_sorting
     1685int TextBlock::visitDepthFirst(TextBlock *blkList, int pos1,
     1686                               TextBlock **sorted, int sortPos,
     1687                               GBool* visited) {
     1688  int pos2;
     1689  TextBlock *blk1, *blk2, *blk3;
     1690  GBool before;
     1691
     1692  if (visited[pos1]) {
     1693    return sortPos;
     1694  }
     1695
     1696  blk1 = this;
     1697
     1698#if 0 // for debugging
     1699  printf("visited: %d %.2f..%.2f %.2f..%.2f\n",
     1700         sortPos, blk1->xMin, blk1->xMax, blk1->yMin, blk1->yMax);
     1701#endif
     1702  visited[pos1] = gTrue;
     1703  pos2 = -1;
     1704  for (blk2 = blkList; blk2; blk2 = blk2->next) {
     1705    pos2++;
     1706    if (visited[pos2]) {
     1707      // skip visited nodes
     1708      continue;
     1709    }
     1710    before = gFalse;
     1711    if (blk2->isBeforeByRule1(blk1)) {
     1712      // Rule (1) blk1 and blk2 overlap, and blk2 is above blk1.
     1713      before = gTrue;
     1714#if 0 // for debugging
     1715      printf("rule1: %.2f..%.2f %.2f..%.2f %.2f..%.2f %.2f..%.2f\n",
     1716             blk2->xMin, blk2->xMax, blk2->yMin, blk2->yMax,
     1717             blk1->xMin, blk1->xMax, blk1->yMin, blk1->yMax);
     1718#endif
     1719    } else if (blk2->isBeforeByRule2(blk1)) {
     1720      // Rule (2) blk2 left of blk1, and no intervening blk3
     1721      //          such that blk1 is before blk3 by rule 1,
     1722      //          and blk3 is before blk2 by rule 1.
     1723      before = gTrue;
     1724      for (blk3 = blkList; blk3; blk3 = blk3->next) {
     1725        if (blk3 == blk2 || blk3 == blk1) {
     1726          continue;
     1727        }
     1728        if (blk1->isBeforeByRule1(blk3) &&
     1729            blk3->isBeforeByRule1(blk2)) {
     1730          before = gFalse;
     1731          break;
     1732        }
     1733      }
     1734#if 0 // for debugging
     1735      if (before) {
     1736        printf("rule2: %.2f..%.2f %.2f..%.2f %.2f..%.2f %.2f..%.2f\n",
     1737               blk1->xMin, blk1->xMax, blk1->yMin, blk1->yMax,
     1738               blk2->xMin, blk2->xMax, blk2->yMin, blk2->yMax);
     1739      }
     1740#endif
     1741    }
     1742    if (before) {
     1743      // blk2 is before blk1, so it needs to be visited
     1744      // before we can add blk1 to the sorted list.
     1745      sortPos = blk2->visitDepthFirst(blkList, pos2, sorted, sortPos, visited);
     1746    }
     1747  }
     1748#if 0 // for debugging
     1749  printf("sorted: %d %.2f..%.2f %.2f..%.2f\n",
     1750         sortPos, blk1->xMin, blk1->xMax, blk1->yMin, blk1->yMax);
     1751#endif
     1752  sorted[sortPos++] = blk1;
     1753  return sortPos;
     1754}
     1755
    16181756//------------------------------------------------------------------------
    16191757// TextFlow
     
    21842322  TextWord *word0, *word1, *word2;
    21852323  TextLine *line;
    2186   TextBlock *blkList, *blkStack, *blk, *lastBlk, *blk0, *blk1;
    2187   TextBlock **blkArray;
     2324  TextBlock *blkList, *blk, *lastBlk, *blk0, *blk1;
    21882325  TextFlow *flow, *lastFlow;
    21892326  TextUnderline *underline;
     
    21952332  int count[4];
    21962333  int lrCount;
    2197   int firstBlkIdx, nBlocksLeft;
    21982334  int col1, col2;
    21992335  int i, j, n;
     
    26882824  }
    26892825
    2690 #if 0 // for debugging 
     2826#if 0 // for debugging
    26912827  printf("*** rotation ***\n");
    26922828  for (rot = 0; rot < 4; ++rot) {
     
    28422978  //----- reading order sort
    28432979
    2844   // sort blocks into yx order (in preparation for reading order sort)
    2845   qsort(blocks, nBlocks, sizeof(TextBlock *), &TextBlock::cmpYXPrimaryRot);
    2846 
    28472980  // compute space on left and right sides of each block
    28482981  for (i = 0; i < nBlocks; ++i) {
     
    28572990
    28582991#if 0 // for debugging
    2859   printf("*** blocks, after yx sort ***\n");
     2992  printf("PAGE\n");
     2993#endif
     2994
     2995  int sortPos = 0;
     2996  GBool *visited = (GBool *)gmallocn(nBlocks, sizeof(GBool));
     2997  for (i = 0; i < nBlocks; i++) {
     2998    visited[i] = gFalse;
     2999  }
     3000  i = -1;
     3001  for (blk1 = blkList; blk1; blk1 = blk1->next) {
     3002    i++;
     3003    sortPos = blk1->visitDepthFirst(blkList, i, blocks, sortPos, visited);
     3004  }
     3005  if (visited) {
     3006    gfree(visited);
     3007  }
     3008
     3009#if 0 // for debugging
     3010  printf("*** blocks, after ro sort ***\n");
    28603011  for (i = 0; i < nBlocks; ++i) {
    28613012    blk = blocks[i];
     
    28773028  }
    28783029  printf("\n");
     3030  fflush(stdout);
    28793031#endif
    28803032
     
    28823034  //~ this needs to be adjusted for writing mode (vertical text)
    28833035  //~ this also needs to account for right-to-left column ordering
    2884   blkArray = (TextBlock **)gmallocn(nBlocks, sizeof(TextBlock *));
    2885   memcpy(blkArray, blocks, nBlocks * sizeof(TextBlock *));
     3036  flow = NULL;
    28863037  while (flows) {
    28873038    flow = flows;
     
    28903041  }
    28913042  flows = lastFlow = NULL;
    2892   firstBlkIdx = 0;
    2893   nBlocksLeft = nBlocks;
    2894   while (nBlocksLeft > 0) {
    2895 
    2896     // find the upper-left-most block
    2897     for (; !blkArray[firstBlkIdx]; ++firstBlkIdx) ;
    2898     i = firstBlkIdx;
    2899     blk = blkArray[i];
    2900     for (j = firstBlkIdx + 1; j < nBlocks; ++j) {
    2901       blk1 = blkArray[j];
    2902       if (blk1) {
    2903         if (blk && blk->secondaryDelta(blk1) > 0) {
    2904           break;
    2905         }
    2906         if (blk1->primaryCmp(blk) < 0) {
    2907           i = j;
    2908           blk = blk1;
    2909         }
    2910       }
    2911     }
    2912     blkArray[i] = NULL;
    2913     --nBlocksLeft;
     3043  // assume blocks are already in reading order,
     3044  // and construct flows accordingly.
     3045  for (i = 0; i < nBlocks; i++) {
     3046    blk = blocks[i];
    29143047    blk->next = NULL;
    2915 
    2916     // create a new flow, starting with the upper-left-most block
     3048    if (flow) {
     3049      blk1 = blocks[i - 1];
     3050      blkSpace = maxBlockSpacing * blk1->lines->words->fontSize;
     3051      if (blk1->secondaryDelta(blk) <= blkSpace &&
     3052          blk->isBelow(blk1) &&
     3053          flow->blockFits(blk, blk1)) {
     3054        flow->addBlock(blk);
     3055        continue;
     3056      }
     3057    }
    29173058    flow = new TextFlow(this, blk);
    29183059    if (lastFlow) {
     
    29223063    }
    29233064    lastFlow = flow;
    2924     fontSize = blk->lines->words->fontSize;
    2925 
    2926     // push the upper-left-most block on the stack
    2927     blk->stackNext = NULL;
    2928     blkStack = blk;
    2929 
    2930     // find the other blocks in this flow
    2931     while (blkStack) {
    2932 
    2933       // find the upper-left-most block under (but within
    2934       // maxBlockSpacing of) the top block on the stack
    2935       blkSpace = maxBlockSpacing * blkStack->lines->words->fontSize;
    2936       blk = NULL;
    2937       i = -1;
    2938       for (j = firstBlkIdx; j < nBlocks; ++j) {
    2939         blk1 = blkArray[j];
    2940         if (blk1) {
    2941           if (blkStack->secondaryDelta(blk1) > blkSpace) {
    2942             break;
    2943           }
    2944           if (blk && blk->secondaryDelta(blk1) > 0) {
    2945             break;
    2946           }
    2947           if (blk1->isBelow(blkStack) &&
    2948               (!blk || blk1->primaryCmp(blk) < 0)) {
    2949             i = j;
    2950             blk = blk1;
    2951           }
    2952         }
    2953       }
    2954 
    2955       // if a suitable block was found, add it to the flow and push it
    2956       // onto the stack
    2957       if (blk && flow->blockFits(blk, blkStack)) {
    2958         blkArray[i] = NULL;
    2959         --nBlocksLeft;
    2960         blk->next = NULL;
    2961         flow->addBlock(blk);
    2962         fontSize = blk->lines->words->fontSize;
    2963         blk->stackNext = blkStack;
    2964         blkStack = blk;
    2965 
    2966       // otherwise (if there is no block under the top block or the
    2967       // block is not suitable), pop the stack
    2968       } else {
    2969         blkStack = blkStack->stackNext;
    2970       }
    2971     }
    2972   }
    2973   gfree(blkArray);
     3065  }
    29743066
    29753067#if 0 // for debugging
     
    35223614GooString *TextSelectionDumper::getText (void)
    35233615{
    3524   GBool oneRot = gTrue;
    35253616  GooString *s;
    35263617  TextLineFrag *frag;
    3527   int i, col;
     3618  int i;
    35283619  GBool multiLine;
    35293620  UnicodeMap *uMap;
     
    35423633
    35433634  if (nFrags > 0) {
    3544     for (i = 0; i < nFrags; ++i) {
    3545       frags[i].computeCoords(oneRot);
    3546     }
    3547     page->assignColumns(frags, nFrags, oneRot);
    3548 
    3549     // if all lines in the region have the same rotation, use it;
    3550     // otherwise, use the page's primary rotation
    3551     if (oneRot) {
    3552       qsort(frags, nFrags, sizeof(TextLineFrag),
    3553             &TextLineFrag::cmpYXLineRot);
    3554     } else {
    3555       qsort(frags, nFrags, sizeof(TextLineFrag),
    3556             &TextLineFrag::cmpYXPrimaryRot);
    3557     }
    3558 
    3559     col = 0;
    35603635    multiLine = gFalse;
    35613636    for (i = 0; i < nFrags; ++i) {
    35623637      frag = &frags[i];
    35633638
    3564       // insert a return
    3565       if (frag->col < col ||
    3566           (i > 0 && fabs(frag->base - frags[i-1].base) >
    3567                       maxIntraLineDelta * frags[i-1].line->words->fontSize)) {
    3568           s->append(eol, eolLen);
    3569         col = 0;
    3570         multiLine = gTrue;
    3571       }
    3572 
    3573       // column alignment
    3574       for (; col < frag->col; ++col) {
    3575         s->append(space, spaceLen);
    3576       }
    3577 
    3578       // get the fragment text
    3579       col += page->dumpFragment(frag->line->text + frag->start, frag->len, uMap, s);
    3580     }
    3581 
    3582     if (multiLine) {
     3639      page->dumpFragment(frag->line->text + frag->start, frag->len, uMap, s);
    35833640      s->append(eol, eolLen);
    35843641    }
     
    38603917                               PDFRectangle *selection,
    38613918                               SelectionStyle style) {
    3862   TextLine *p, *begin, *end;
    38633919  PDFRectangle child_selection;
    3864   double start_x, start_y, stop_x, stop_y;
    3865 
    3866   begin = NULL;
    3867   end = NULL;
    3868   start_x = selection->x1;
    3869   start_y = selection->y1;
    3870   stop_x = selection->x2;
    3871   stop_y = selection->y2;
    3872  
    3873   for (p = lines; p != NULL; p = p->next) {
    3874     if (selection->x1 < p->xMax && selection->y1 < p->yMax &&
    3875         selection->x2 < p->xMax && selection->y2 < p->yMax && begin == NULL) {
    3876       begin = p;
    3877       if (selection->x1 < selection->x2) {
    3878         start_x = selection->x1;
    3879         start_y = selection->y1;
    3880         stop_x = selection->x2;
    3881         stop_y = selection->y2;
     3920  double x[2], y[2], d, best_d[2];
     3921  TextLine *p, *best_line[2];
     3922  int i, count = 0, best_count[2], start, stop;
     3923  GBool all[2];
     3924
     3925  x[0] = selection->x1;
     3926  y[0] = selection->y1;
     3927  x[1] = selection->x2;
     3928  y[1] = selection->y2;
     3929
     3930  for (i = 0; i < 2; i++) {
     3931    // the first/last lines are often not nearest
     3932    // the corners, so we have to force them to be
     3933    // selected when the selection runs outside this
     3934    // block.
     3935    if (page->primaryLR) {
     3936      all[i] = x[i] >= this->xMax && y[i] >= this->yMax;
     3937      if (x[i] <= this->xMin && y[i] <= this->yMin) {
     3938        best_line[i] = this->lines;
     3939        best_count[i] = 1;
    38823940      } else {
    3883         start_x = selection->x2;
    3884         start_y = selection->y2;
    3885         stop_x = selection->x1;
    3886         stop_y = selection->y1;
    3887       }
    3888     } else if (selection->x1 < p->xMax && selection->y1 < p->yMax && begin == NULL) {
    3889       begin = p;
    3890       start_x = selection->x1;
    3891       start_y = selection->y1;
    3892       stop_x = selection->x2;
    3893       stop_y = selection->y2;
    3894     } else if (selection->x2 < p->xMax && selection->y2 < p->yMax && begin == NULL) {
    3895       begin = p;
    3896       start_x = selection->x2;
    3897       start_y = selection->y2;
    3898       stop_x = selection->x1;
    3899       stop_y = selection->y1;
    3900     }
    3901 
    3902     if (((selection->x1 > p->xMin && selection->y1 > p->yMin) ||
    3903          (selection->x2 > p->xMin && selection->y2 > p->yMin))
    3904         && (begin != NULL))
    3905       end = p->next;
    3906   }
    3907 
    3908   /* Skip empty selection. */
    3909   if (end == begin)
     3941        best_line[i] = NULL;
     3942        best_count[i] = 0;
     3943      }
     3944    } else {
     3945      all[i] = x[i] <= this->xMin && y[i] >= this->yMax;
     3946      if (x[i] >= this->xMax && y[i] <= this->yMin) {
     3947        best_line[i] = this->lines;
     3948        best_count[i] = 1;
     3949      } else {
     3950        best_line[i] = NULL;
     3951        best_count[i] = 0;
     3952      }
     3953    }
     3954    best_d[i] = 0;
     3955  }
     3956
     3957  // find the nearest line to the selection points
     3958  // using the manhattan distance.
     3959  for (p = this->lines; p; p = p->next) {
     3960    count++;
     3961    for (i = 0; i < 2; i++) {
     3962      d = fmax(p->xMin - x[i], 0.0) +
     3963        fmax(x[i] - p->xMax, 0.0) +
     3964        fmax(p->yMin - y[i], 0.0) +
     3965        fmax(y[i] - p->yMax, 0.0);
     3966      if (!best_line[i] || all[i] ||
     3967          d < best_d[i]) {
     3968        best_line[i] = p;
     3969        best_count[i] = count;
     3970        best_d[i] = d;
     3971      }
     3972    }
     3973  }
     3974  // assert: best is always set.
     3975  if (!best_line[0] || !best_line[1]) {
    39103976    return;
    3911 
    3912   visitor->visitBlock (this, begin, end, selection);
    3913 
    3914   for (p = begin; p != end; p = p->next) {
    3915     if (p == begin && style != selectionStyleLine) {
    3916       child_selection.x1 = start_x;
    3917       child_selection.y1 = start_y;
     3977  }
     3978
     3979  // Now decide which point was first.
     3980  if (best_count[0] < best_count[1] ||
     3981      (best_count[0] == best_count[1] &&
     3982       y[0] < y[1])) {
     3983    start = 0;
     3984    stop = 1;
     3985  } else {
     3986    start = 1;
     3987    stop = 0;
     3988  }
     3989
     3990  visitor->visitBlock(this, best_line[start], best_line[stop], selection);
     3991
     3992  for (p = best_line[start]; p; p = p->next) {
     3993    if (page->primaryLR) {
     3994      child_selection.x1 = p->xMin;
     3995      child_selection.x2 = p->xMax;
    39183996    } else {
    3919       child_selection.x1 = 0;
    3920       child_selection.y1 = 0;
    3921     }
    3922     if (p->next == end && style != selectionStyleLine) {
    3923       child_selection.x2 = stop_x;
    3924       child_selection.y2 = stop_y;
     3997      child_selection.x1 = p->xMax;
     3998      child_selection.x2 = p->xMin;
     3999    }
     4000    child_selection.y1 = p->yMin;
     4001    child_selection.y2 = p->yMax;
     4002    if (style == selectionStyleLine) {
     4003      if (p == best_line[start]) {
     4004        child_selection.x1 = 0;
     4005        child_selection.y1 = 0;
     4006      }
     4007      if (p == best_line[stop]) {
     4008        child_selection.x2 = page->pageWidth;
     4009        child_selection.y2 = page->pageHeight;
     4010      }
    39254011    } else {
    3926       child_selection.x2 = page->pageWidth;
    3927       child_selection.y2 = page->pageHeight;
    3928     }
    3929 
     4012      if (p == best_line[start]) {
     4013        child_selection.x1 = fmax(p->xMin, fmin(p->xMax, x[start]));
     4014        child_selection.y1 = fmax(p->yMin, fmin(p->yMax, y[start]));
     4015      }
     4016      if (p == best_line[stop]) {
     4017        child_selection.x2 = fmax(p->xMin, fmin(p->xMax, x[stop]));
     4018        child_selection.y2 = fmax(p->yMin, fmin(p->yMax, y[stop]));
     4019      }
     4020    }
    39304021    p->visitSelection(visitor, &child_selection, style);
     4022    if (p == best_line[stop]) {
     4023      return;
     4024    }
    39314025  }
    39324026}
     
    39364030                              SelectionStyle style)
    39374031{
    3938   int i, begin, end;
    39394032  PDFRectangle child_selection;
    3940   double start_x, start_y, stop_x, stop_y;
    3941   TextBlock *b;
    3942 
    3943   begin = nBlocks;
    3944   end = 0;
    3945   start_x = selection->x1;
    3946   start_y = selection->y1;
    3947   stop_x = selection->x2;
    3948   stop_y = selection->y2;
    3949 
    3950   for (i = 0; i < nBlocks; i++) {
    3951     b = blocks[i];
    3952 
    3953     if (selection->x1 < b->xMax && selection->y1 < b->yMax &&
    3954         selection->x2 < b->xMax && selection->y2 < b->yMax && i < begin) {
    3955       begin = i;
    3956       if (selection->y1 < selection->y2) {
    3957         start_x = selection->x1;
    3958         start_y = selection->y1;
    3959         stop_x = selection->x2;
    3960         stop_y = selection->y2;
     4033  double x[2], y[2], d, best_d[2];
     4034  double xMin, yMin, xMax, yMax;
     4035  TextFlow *flow, *best_flow[2];
     4036  TextBlock *blk, *best_block[2];
     4037  int i, count = 0, best_count[2], start, stop;
     4038
     4039  if (!flows)
     4040    return;
     4041
     4042  x[0] = selection->x1;
     4043  y[0] = selection->y1;
     4044  x[1] = selection->x2;
     4045  y[1] = selection->y2;
     4046
     4047  xMin = pageWidth;
     4048  yMin = pageHeight;
     4049  xMax = 0.0;
     4050  yMax = 0.0;
     4051
     4052  for (i = 0; i < 2; i++) {
     4053    best_block[i] = NULL;
     4054    best_flow[i] = NULL;
     4055    best_count[i] = 0;
     4056    best_d[i] = 0;
     4057  }
     4058
     4059  // find the nearest blocks to the selection points
     4060  // using the manhattan distance.
     4061  for (flow = flows; flow; flow = flow->next) {
     4062    for (blk = flow->blocks; blk; blk = blk->next) {
     4063      count++;
     4064      // the first/last blocks in reading order are
     4065      // often not the closest to the page corners;
     4066      // track the corners, force those blocks to
     4067      // be selected if the selection runs across
     4068      // multiple pages.
     4069      xMin = fmin(xMin, blk->xMin);
     4070      yMin = fmin(yMin, blk->yMin);
     4071      xMax = fmax(xMax, blk->xMax);
     4072      yMax = fmax(yMax, blk->yMax);
     4073      for (i = 0; i < 2; i++) {
     4074        d = fmax(blk->xMin - x[i], 0.0) +
     4075          fmax(x[i] - blk->xMax, 0.0) +
     4076          fmax(blk->yMin - y[i], 0.0) +
     4077          fmax(y[i] - blk->yMax, 0.0);
     4078        if (!best_block[i] ||
     4079            d < best_d[i] ||
     4080            (!blk->next && !flow->next &&
     4081             x[i] > xMax && y[i] > yMax)) {
     4082          best_block[i] = blk;
     4083          best_flow[i] = flow;
     4084          best_count[i] = count;
     4085          best_d[i] = d;
     4086        }
     4087      }
     4088    }
     4089  }
     4090  for (i = 0; i < 2; i++) {
     4091    if (primaryLR) {
     4092      if (x[i] < xMin && y[i] < yMin) {
     4093        best_block[i] = flows->blocks;
     4094        best_flow[i] = flows;
     4095        best_count[i] = 1;
     4096      }
     4097    } else {
     4098      if (x[i] > xMax && y[i] < yMin) {
     4099        best_block[i] = flows->blocks;
     4100        best_flow[i] = flows;
     4101        best_count[i] = 1;
     4102      }
     4103    }
     4104  }
     4105  // assert: best is always set.
     4106  if (!best_block[0] || !best_block[1]) {
     4107    return;
     4108  }
     4109
     4110  // Now decide which point was first.
     4111  if (best_count[0] < best_count[1] ||
     4112      (best_count[0] == best_count[1] && y[0] < y[1])) {
     4113    start = 0;
     4114    stop = 1;
     4115  } else {
     4116    start = 1;
     4117    stop = 0;
     4118  }
     4119
     4120  for (flow = best_flow[start]; flow; flow = flow->next) {
     4121    if (flow == best_flow[start]) {
     4122      blk = best_block[start];
     4123    } else {
     4124      blk = flow->blocks;
     4125    }
     4126    for (; blk; blk = blk->next) {
     4127      if (primaryLR) {
     4128        child_selection.x1 = blk->xMin;
     4129        child_selection.x2 = blk->xMax;
    39614130      } else {
    3962         start_x = selection->x2;
    3963         start_y = selection->y2;
    3964         stop_x = selection->x1;
    3965         stop_y = selection->y1;
    3966       }
    3967     } else if (selection->x1 < b->xMax && selection->y1 < b->yMax && i < begin) {
    3968       begin = i;
    3969       start_x = selection->x1;
    3970       start_y = selection->y1;
    3971       stop_x = selection->x2;
    3972       stop_y = selection->y2;
    3973     } else if (selection->x2 < b->xMax && selection->y2 < b->yMax && i < begin) {
    3974       begin = i;
    3975       start_x = selection->x2;
    3976       start_y = selection->y2;
    3977       stop_x = selection->x1;
    3978       stop_y = selection->y1;
    3979     }
    3980 
    3981     if ((selection->x1 > b->xMin && selection->y1 > b->yMin) ||
    3982         (selection->x2 > b->xMin && selection->y2 > b->yMin))
    3983       end = i + 1;
    3984   }
    3985 
    3986   for (i = begin; i < end; i++) {
    3987     if (blocks[i]->xMin < start_x && start_x < blocks[i]->xMax &&
    3988         blocks[i]->yMin < start_y && start_y < blocks[i]->yMax) {
    3989       child_selection.x1 = start_x;
    3990       child_selection.y1 = start_y;
    3991     } else {
    3992       child_selection.x1 = 0;
    3993       child_selection.y1 = 0;
    3994     }
    3995     if (blocks[i]->xMin < stop_x && stop_x < blocks[i]->xMax &&
    3996         blocks[i]->yMin < stop_y && stop_y < blocks[i]->yMax) {
    3997       child_selection.x2 = stop_x;
    3998       child_selection.y2 = stop_y;
    3999     } else {
    4000       child_selection.x2 = pageWidth;
    4001       child_selection.y2 = pageHeight;
    4002     }
    4003 
    4004     blocks[i]->visitSelection(visitor, &child_selection, style);
     4131        child_selection.x1 = blk->xMax;
     4132        child_selection.x2 = blk->xMin;
     4133      }
     4134      child_selection.y1 = blk->yMin;
     4135      child_selection.y2 = blk->yMax;
     4136      if (blk == best_block[start]) {
     4137        child_selection.x1 = fmax(blk->xMin, fmin(blk->xMax, x[start]));
     4138        child_selection.y1 = fmax(blk->yMin, fmin(blk->yMax, y[start]));
     4139      }
     4140      if (blk == best_block[stop]) {
     4141        child_selection.x2 = fmax(blk->xMin, fmin(blk->xMax, x[stop]));
     4142        child_selection.y2 = fmax(blk->yMin, fmin(blk->yMax, y[stop]));
     4143        blk->visitSelection(visitor, &child_selection, style);
     4144        return;
     4145      }
     4146      blk->visitSelection(visitor, &child_selection, style);
     4147    }
    40054148  }
    40064149}
     
    42874430          (*outputFunc)(outputStream, s->getCString(), s->getLength());
    42884431          delete s;
    4289           if (!line->hyphenated) {
    4290             if (line->next) {
    4291               (*outputFunc)(outputStream, space, spaceLen);
    4292             } else if (blk->next) {
    4293               //~ this is a bit of a kludge - we should really do a more
    4294               //~ intelligent determination of paragraphs
    4295               if (blk->next->lines->words->fontSize ==
    4296                   blk->lines->words->fontSize) {
    4297                 (*outputFunc)(outputStream, space, spaceLen);
    4298               } else {
    4299                 (*outputFunc)(outputStream, eol, eolLen);
    4300               }
    4301             }
     4432          // output a newline when a hyphen is not suppressed
     4433          if (n == line->len) {
     4434            (*outputFunc)(outputStream, eol, eolLen);
    43024435          }
    43034436        }
    43044437      }
    4305       (*outputFunc)(outputStream, eol, eolLen);
    43064438      (*outputFunc)(outputStream, eol, eolLen);
    43074439    }
Note: See TracChangeset for help on using the changeset viewer.