| | @@ -258,11 +258,10 @@ |
| 258 | 258 | int iRail = pBottom->iRail; |
| 259 | 259 | GraphRow *pCurrent; |
| 260 | 260 | GraphRow *pPrior; |
| 261 | 261 | u64 mask = ((u64)1)<<iRail; |
| 262 | 262 | |
| 263 | | - pBottom->iRail = iRail; |
| 264 | 263 | pBottom->railInUse |= mask; |
| 265 | 264 | pPrior = pBottom; |
| 266 | 265 | for(pCurrent=pBottom->pChild; pCurrent; pCurrent=pCurrent->pChild){ |
| 267 | 266 | assert( pPrior->idx > pCurrent->idx ); |
| 268 | 267 | assert( pCurrent->iRail<0 ); |
| | @@ -344,14 +343,16 @@ |
| 344 | 343 | /* |
| 345 | 344 | ** Compute the complete graph |
| 346 | 345 | */ |
| 347 | 346 | void graph_finish(GraphContext *p, int omitDescenders){ |
| 348 | 347 | GraphRow *pRow, *pDesc, *pDup, *pLoop, *pParent; |
| 349 | | - int i; |
| 348 | + int i, j; |
| 350 | 349 | u64 mask; |
| 351 | 350 | int hasDup = 0; /* True if one or more isDup entries */ |
| 352 | 351 | const char *zTrunk; |
| 352 | + int railRid[GR_MAX_RAIL]; /* Maps rails to rids for lines |
| 353 | + that enter from bottom of screen */ |
| 353 | 354 | |
| 354 | 355 | if( p==0 || p->pFirst==0 || p->nErr ) return; |
| 355 | 356 | p->nErr = 1; /* Assume an error until proven otherwise */ |
| 356 | 357 | |
| 357 | 358 | /* Initialize all rows */ |
| | @@ -366,10 +367,11 @@ |
| 366 | 367 | pDup->isDup = 1; |
| 367 | 368 | } |
| 368 | 369 | hashInsert(p, pRow, 1); |
| 369 | 370 | } |
| 370 | 371 | p->mxRail = -1; |
| 372 | + memset(railRid, 0, sizeof(railRid)); |
| 371 | 373 | |
| 372 | 374 | /* Purge merge-parents that are out-of-graph if descenders are not |
| 373 | 375 | ** drawn. |
| 374 | 376 | ** |
| 375 | 377 | ** Each node has one primary parent and zero or more "merge" parents. |
| | @@ -458,10 +460,13 @@ |
| 458 | 460 | } |
| 459 | 461 | if( p->mxRail>=GR_MAX_RAIL ) return; |
| 460 | 462 | mask = BIT(pRow->iRail); |
| 461 | 463 | if( !omitDescenders ){ |
| 462 | 464 | pRow->bDescender = pRow->nParent>0; |
| 465 | + if( pRow->bDescender ){ |
| 466 | + railRid[pRow->iRail] = pRow->aParent[0]; |
| 467 | + } |
| 463 | 468 | for(pLoop=pRow; pLoop; pLoop=pLoop->pNext){ |
| 464 | 469 | pLoop->railInUse |= mask; |
| 465 | 470 | } |
| 466 | 471 | } |
| 467 | 472 | assignChildrenToRail(pRow); |
| | @@ -536,12 +541,22 @@ |
| 536 | 541 | for(i=1; i<pRow->nParent; i++){ |
| 537 | 542 | int parentRid = pRow->aParent[i]; |
| 538 | 543 | pDesc = hashFind(p, parentRid); |
| 539 | 544 | if( pDesc==0 ){ |
| 540 | 545 | /* Merge from a node that is off-screen */ |
| 541 | | - int iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); |
| 542 | | - if( p->mxRail>=GR_MAX_RAIL ) return; |
| 546 | + int iMrail = -1; |
| 547 | + for(j=0; j<GR_MAX_RAIL; j++){ |
| 548 | + if( railRid[j]==parentRid ){ |
| 549 | + iMrail = j; |
| 550 | + break; |
| 551 | + } |
| 552 | + } |
| 553 | + if( iMrail==-1 ){ |
| 554 | + iMrail = findFreeRail(p, pRow->idx, p->nRow, 0); |
| 555 | + if( p->mxRail>=GR_MAX_RAIL ) return; |
| 556 | + railRid[iMrail] = parentRid; |
| 557 | + } |
| 543 | 558 | mask = BIT(iMrail); |
| 544 | 559 | pRow->mergeIn[iMrail] = 1; |
| 545 | 560 | pRow->mergeDown |= mask; |
| 546 | 561 | for(pLoop=pRow->pNext; pLoop; pLoop=pLoop->pNext){ |
| 547 | 562 | pLoop->railInUse |= mask; |
| 548 | 563 | |