Fossil SCM
Update to a new version of pikchr.c with improved text bounding box computation.
Commit
1f2b6cedadf4e82a80720e4f227343a568f2272cc04d976c0195f14092da68b6
Parent
2b556f1cc81aeaa…
1 file changed
+72
-39
+72
-39
| --- src/pikchr.c | ||
| +++ src/pikchr.c | ||
| @@ -366,11 +366,11 @@ | ||
| 366 | 366 | static void pik_append_xy(Pik*,const char*,PNum,PNum); |
| 367 | 367 | static void pik_append_dis(Pik*,const char*,PNum,const char*); |
| 368 | 368 | static void pik_append_arc(Pik*,PNum,PNum,PNum,PNum); |
| 369 | 369 | static void pik_append_clr(Pik*,const char*,PNum,const char*); |
| 370 | 370 | static void pik_append_style(Pik*,PElem*); |
| 371 | -static void pik_append_txt(Pik*,PElem*); | |
| 371 | +static void pik_append_txt(Pik*,PElem*, PBox*); | |
| 372 | 372 | static void pik_draw_arrowhead(Pik*,PPoint*pFrom,PPoint*pTo,PElem*); |
| 373 | 373 | static void pik_chop(Pik*,PPoint*pFrom,PPoint*pTo,PNum); |
| 374 | 374 | static void pik_error(Pik*,PToken*,const char*); |
| 375 | 375 | static void pik_elist_free(Pik*,PEList*); |
| 376 | 376 | static void pik_elem_free(Pik*,PElem*); |
| @@ -401,11 +401,11 @@ | ||
| 401 | 401 | static PElem *pik_find_byname(Pik*,PElem*,PToken*); |
| 402 | 402 | static PPoint pik_place_of_elem(Pik*,PElem*,PToken*); |
| 403 | 403 | static int pik_bbox_isempty(PBox*); |
| 404 | 404 | static void pik_bbox_init(PBox*); |
| 405 | 405 | static void pik_bbox_addbox(PBox*,PBox*); |
| 406 | -static void pik_bbox_addpt(PBox*,PPoint*); | |
| 406 | +static void pik_bbox_add_xy(PBox*,PNum,PNum); | |
| 407 | 407 | static void pik_bbox_addellipse(PBox*,PNum x,PNum y,PNum rx,PNum ry); |
| 408 | 408 | static void pik_add_txt(Pik*,PToken*,int); |
| 409 | 409 | static int pik_text_length(const PToken *pToken); |
| 410 | 410 | static void pik_size_to_fit(Pik*,PToken*); |
| 411 | 411 | static int pik_text_position(Pik*,int,PToken*); |
| @@ -3308,11 +3308,11 @@ | ||
| 3308 | 3308 | pik_append_xy(p," ", t.x, t.y); |
| 3309 | 3309 | pik_append(p,"\" ",2); |
| 3310 | 3310 | pik_append_style(p,pElem); |
| 3311 | 3311 | pik_append(p,"\" />\n", -1); |
| 3312 | 3312 | |
| 3313 | - pik_append_txt(p, pElem); | |
| 3313 | + pik_append_txt(p, pElem, 0); | |
| 3314 | 3314 | } |
| 3315 | 3315 | |
| 3316 | 3316 | |
| 3317 | 3317 | /* Methods for the "arrow" class */ |
| 3318 | 3318 | static void arrowInit(Pik *p, PElem *pElem){ |
| @@ -3449,11 +3449,11 @@ | ||
| 3449 | 3449 | pik_append(p,"Z\" ",-1); |
| 3450 | 3450 | } |
| 3451 | 3451 | pik_append_style(p,pElem); |
| 3452 | 3452 | pik_append(p,"\" />\n", -1); |
| 3453 | 3453 | } |
| 3454 | - pik_append_txt(p, pElem); | |
| 3454 | + pik_append_txt(p, pElem, 0); | |
| 3455 | 3455 | } |
| 3456 | 3456 | |
| 3457 | 3457 | /* Methods for the "circle" class */ |
| 3458 | 3458 | static void circleInit(Pik *p, PElem *pElem){ |
| 3459 | 3459 | pElem->w = pik_value(p, "circlerad",9,0)*2; |
| @@ -3508,11 +3508,11 @@ | ||
| 3508 | 3508 | pik_append_y(p," cy=\"", pt.y, "\""); |
| 3509 | 3509 | pik_append_dis(p," r=\"", r, "\" "); |
| 3510 | 3510 | pik_append_style(p,pElem); |
| 3511 | 3511 | pik_append(p,"\" />\n", -1); |
| 3512 | 3512 | } |
| 3513 | - pik_append_txt(p, pElem); | |
| 3513 | + pik_append_txt(p, pElem, 0); | |
| 3514 | 3514 | } |
| 3515 | 3515 | |
| 3516 | 3516 | /* Methods for the "cylinder" class */ |
| 3517 | 3517 | static void cylinderInit(Pik *p, PElem *pElem){ |
| 3518 | 3518 | pElem->w = pik_value(p, "cylwid",6,0); |
| @@ -3533,11 +3533,11 @@ | ||
| 3533 | 3533 | pik_append_arc(p,w2,rad,pt.x+w2,pt.y+h2-rad); |
| 3534 | 3534 | pik_append(p,"\" ",-1); |
| 3535 | 3535 | pik_append_style(p,pElem); |
| 3536 | 3536 | pik_append(p,"\" />\n", -1); |
| 3537 | 3537 | } |
| 3538 | - pik_append_txt(p, pElem); | |
| 3538 | + pik_append_txt(p, pElem, 0); | |
| 3539 | 3539 | } |
| 3540 | 3540 | static PPoint cylinderOffset(Pik *p, PElem *pElem, int cp){ |
| 3541 | 3541 | PPoint pt; |
| 3542 | 3542 | PNum w2 = pElem->w*0.5; |
| 3543 | 3543 | PNum h1 = pElem->h*0.5; |
| @@ -3580,11 +3580,11 @@ | ||
| 3580 | 3580 | pik_append_y(p," cy=\"", pt.y, "\""); |
| 3581 | 3581 | pik_append_dis(p," r=\"", r, "\""); |
| 3582 | 3582 | pik_append_style(p,pElem); |
| 3583 | 3583 | pik_append(p,"\" />\n", -1); |
| 3584 | 3584 | } |
| 3585 | - pik_append_txt(p, pElem); | |
| 3585 | + pik_append_txt(p, pElem, 0); | |
| 3586 | 3586 | } |
| 3587 | 3587 | |
| 3588 | 3588 | |
| 3589 | 3589 | |
| 3590 | 3590 | /* Methods for the "ellipse" class */ |
| @@ -3636,11 +3636,11 @@ | ||
| 3636 | 3636 | pik_append_dis(p," rx=\"", w/2.0, "\""); |
| 3637 | 3637 | pik_append_dis(p," ry=\"", h/2.0, "\" "); |
| 3638 | 3638 | pik_append_style(p,pElem); |
| 3639 | 3639 | pik_append(p,"\" />\n", -1); |
| 3640 | 3640 | } |
| 3641 | - pik_append_txt(p, pElem); | |
| 3641 | + pik_append_txt(p, pElem, 0); | |
| 3642 | 3642 | } |
| 3643 | 3643 | |
| 3644 | 3644 | /* Methods for the "line" class */ |
| 3645 | 3645 | static void lineInit(Pik *p, PElem *pElem){ |
| 3646 | 3646 | pElem->w = pik_value(p, "linewid",7,0); |
| @@ -3670,11 +3670,11 @@ | ||
| 3670 | 3670 | } |
| 3671 | 3671 | pik_append(p,"\" ",-1); |
| 3672 | 3672 | pik_append_style(p,pElem); |
| 3673 | 3673 | pik_append(p,"\" />\n", -1); |
| 3674 | 3674 | } |
| 3675 | - pik_append_txt(p, pElem); | |
| 3675 | + pik_append_txt(p, pElem, 0); | |
| 3676 | 3676 | } |
| 3677 | 3677 | |
| 3678 | 3678 | /* Methods for the "move" class */ |
| 3679 | 3679 | static void moveInit(Pik *p, PElem *pElem){ |
| 3680 | 3680 | pElem->w = pik_value(p, "movewid",7,0); |
| @@ -3773,11 +3773,11 @@ | ||
| 3773 | 3773 | if( pElem->rarrow ){ |
| 3774 | 3774 | pik_draw_arrowhead(p,&pElem->aPath[n-2],&pElem->aPath[n-1],pElem); |
| 3775 | 3775 | } |
| 3776 | 3776 | radiusPath(p,pElem,pElem->rad); |
| 3777 | 3777 | } |
| 3778 | - pik_append_txt(p, pElem); | |
| 3778 | + pik_append_txt(p, pElem, 0); | |
| 3779 | 3779 | } |
| 3780 | 3780 | |
| 3781 | 3781 | |
| 3782 | 3782 | /* Methods for the "text" class */ |
| 3783 | 3783 | static void textInit(Pik *p, PElem *pElem){ |
| @@ -4229,13 +4229,17 @@ | ||
| 4229 | 4229 | } |
| 4230 | 4230 | } |
| 4231 | 4231 | } |
| 4232 | 4232 | } |
| 4233 | 4233 | |
| 4234 | -/* Append multiple <text> SGV element for the text fields of the PElem | |
| 4234 | +/* Append multiple <text> SGV element for the text fields of the PElem. | |
| 4235 | +** | |
| 4236 | +** Or, if pBox!=NULL, then do not actually do any output. Instead | |
| 4237 | +** guess at how large the various <text> elements would be and where | |
| 4238 | +** the will be located and expand the pBox to include them. | |
| 4235 | 4239 | */ |
| 4236 | -static void pik_append_txt(Pik *p, PElem *pElem){ | |
| 4240 | +static void pik_append_txt(Pik *p, PElem *pElem, PBox *pBox){ | |
| 4237 | 4241 | PNum dy; /* Half the height of a single line of text */ |
| 4238 | 4242 | PNum dy2; /* Extra vertical space around the center */ |
| 4239 | 4243 | int n, i, nz; |
| 4240 | 4244 | PNum x, y, orig_y; |
| 4241 | 4245 | const char *z; |
| @@ -4264,10 +4268,28 @@ | ||
| 4264 | 4268 | orig_y = y = pElem->ptAt.y; |
| 4265 | 4269 | if( t->eCode & TP_ABOVE2 ) y += dy2 + 3*dy; |
| 4266 | 4270 | if( t->eCode & TP_ABOVE ) y += dy2 + dy; |
| 4267 | 4271 | if( t->eCode & TP_BELOW ) y -= dy2 + dy; |
| 4268 | 4272 | if( t->eCode & TP_BELOW2 ) y -= dy2 + 3*dy; |
| 4273 | + | |
| 4274 | + if( pBox!=0 ){ | |
| 4275 | + /* If pBox is not NULL, do not draw any <text>. Instead, just expand | |
| 4276 | + ** pBox to include the text */ | |
| 4277 | + PNum cw = pik_text_length(t)*p->charWidth; | |
| 4278 | + PNum ch = p->charHeight*0.5; | |
| 4279 | + if( t->eCode & TP_RJUST ){ | |
| 4280 | + pik_bbox_add_xy(pBox, x, y-ch); | |
| 4281 | + pik_bbox_add_xy(pBox, x-cw, y+ch); | |
| 4282 | + }else if( t->eCode & TP_LJUST ){ | |
| 4283 | + pik_bbox_add_xy(pBox, x, y-ch); | |
| 4284 | + pik_bbox_add_xy(pBox, x+cw, y+ch); | |
| 4285 | + }else{ | |
| 4286 | + pik_bbox_add_xy(pBox, x+cw/2, y+ch); | |
| 4287 | + pik_bbox_add_xy(pBox, x-cw/2, y-ch); | |
| 4288 | + } | |
| 4289 | + continue; | |
| 4290 | + } | |
| 4269 | 4291 | |
| 4270 | 4292 | pik_append_x(p, "<text x=\"", x, "\""); |
| 4271 | 4293 | pik_append_y(p, " y=\"", y, "\""); |
| 4272 | 4294 | if( t->eCode & TP_RJUST ){ |
| 4273 | 4295 | pik_append(p, " text-anchor=\"end\"", -1); |
| @@ -4442,20 +4464,22 @@ | ||
| 4442 | 4464 | } |
| 4443 | 4465 | |
| 4444 | 4466 | /* Enlarge the PBox of the first argument, if necessary, so that |
| 4445 | 4467 | ** it contains the PPoint in the second argument |
| 4446 | 4468 | */ |
| 4447 | -static void pik_bbox_addpt(PBox *pA, PPoint *pPt){ | |
| 4469 | +static void pik_bbox_add_xy(PBox *pA, PNum x, PNum y){ | |
| 4448 | 4470 | if( pik_bbox_isempty(pA) ){ |
| 4449 | - pA->ne = *pPt; | |
| 4450 | - pA->sw = *pPt; | |
| 4471 | + pA->ne.x = x; | |
| 4472 | + pA->ne.y = y; | |
| 4473 | + pA->sw.x = x; | |
| 4474 | + pA->sw.y = y; | |
| 4451 | 4475 | return; |
| 4452 | 4476 | } |
| 4453 | - if( pA->sw.x>pPt->x ) pA->sw.x = pPt->x; | |
| 4454 | - if( pA->sw.y>pPt->y ) pA->sw.y = pPt->y; | |
| 4455 | - if( pA->ne.x<pPt->x ) pA->ne.x = pPt->x; | |
| 4456 | - if( pA->ne.y<pPt->y ) pA->ne.y = pPt->y; | |
| 4477 | + if( pA->sw.x>x ) pA->sw.x = x; | |
| 4478 | + if( pA->sw.y>y ) pA->sw.y = y; | |
| 4479 | + if( pA->ne.x<x ) pA->ne.x = x; | |
| 4480 | + if( pA->ne.y<y ) pA->ne.y = y; | |
| 4457 | 4481 | } |
| 4458 | 4482 | |
| 4459 | 4483 | /* Enlarge the PBox so that it is able to contain an ellipse |
| 4460 | 4484 | ** centered at x,y and with radiuses rx and ry. |
| 4461 | 4485 | */ |
| @@ -5663,11 +5687,11 @@ | ||
| 5663 | 5687 | pElem->nPath = 0; |
| 5664 | 5688 | }else{ |
| 5665 | 5689 | pElem->nPath = p->nTPath; |
| 5666 | 5690 | for(i=0; i<p->nTPath; i++){ |
| 5667 | 5691 | pElem->aPath[i] = p->aTPath[i]; |
| 5668 | - pik_bbox_addpt(&pElem->bbox, &pElem->aPath[i]); | |
| 5692 | + pik_bbox_add_xy(&pElem->bbox, pElem->aPath[i].x, pElem->aPath[i].y); | |
| 5669 | 5693 | } |
| 5670 | 5694 | } |
| 5671 | 5695 | |
| 5672 | 5696 | /* "chop" processing: |
| 5673 | 5697 | ** If the line goes to the center of an object with an |
| @@ -5787,10 +5811,36 @@ | ||
| 5787 | 5811 | pik_elist_render(p, pElem->pSublist); |
| 5788 | 5812 | } |
| 5789 | 5813 | } |
| 5790 | 5814 | }while( bMoreToDo ); |
| 5791 | 5815 | } |
| 5816 | + | |
| 5817 | +/* Add all elements of the list pEList to the bounding box | |
| 5818 | +*/ | |
| 5819 | +static void pik_bbox_add_elist(Pik *p, PEList *pEList, PNum wArrow){ | |
| 5820 | + int i; | |
| 5821 | + for(i=0; i<pEList->n; i++){ | |
| 5822 | + PElem *pElem = pEList->a[i]; | |
| 5823 | + pik_bbox_addbox(&p->bbox, &pElem->bbox); | |
| 5824 | + pik_append_txt(p, pElem, &p->bbox); | |
| 5825 | + if( pElem->pSublist ) pik_bbox_add_elist(p, pElem->pSublist, wArrow); | |
| 5826 | + | |
| 5827 | + | |
| 5828 | + /* Expand the bounding box to account for arrowheads on lines */ | |
| 5829 | + if( pElem->type->isLine && pElem->nPath>0 ){ | |
| 5830 | + if( pElem->larrow ){ | |
| 5831 | + pik_bbox_addellipse(&p->bbox, pElem->aPath[0].x, pElem->aPath[0].y, | |
| 5832 | + wArrow, wArrow); | |
| 5833 | + } | |
| 5834 | + if( pElem->rarrow ){ | |
| 5835 | + int j = pElem->nPath-1; | |
| 5836 | + pik_bbox_addellipse(&p->bbox, pElem->aPath[j].x, pElem->aPath[j].y, | |
| 5837 | + wArrow, wArrow); | |
| 5838 | + } | |
| 5839 | + } | |
| 5840 | + } | |
| 5841 | +} | |
| 5792 | 5842 | |
| 5793 | 5843 | /* Recompute key layout parameters from variables. */ |
| 5794 | 5844 | static void pik_compute_layout_settings(Pik *p){ |
| 5795 | 5845 | PNum thickness; /* Line thickness */ |
| 5796 | 5846 | PNum wArrow; /* Width of arrowheads */ |
| @@ -5814,11 +5864,10 @@ | ||
| 5814 | 5864 | |
| 5815 | 5865 | /* Render a list of elements. Write the SVG into p->zOut. |
| 5816 | 5866 | ** Delete the input element_list before returnning. |
| 5817 | 5867 | */ |
| 5818 | 5868 | static void pik_render(Pik *p, PEList *pEList){ |
| 5819 | - int i, j; | |
| 5820 | 5869 | if( pEList==0 ) return; |
| 5821 | 5870 | if( p->nErr==0 ){ |
| 5822 | 5871 | PNum thickness; /* Stroke width */ |
| 5823 | 5872 | PNum margin; /* Extra bounding box margin */ |
| 5824 | 5873 | PNum leftmargin; /* Extra bounding box area on the left */ |
| @@ -5835,27 +5884,11 @@ | ||
| 5835 | 5884 | wArrow = p->wArrow*thickness; |
| 5836 | 5885 | |
| 5837 | 5886 | /* Compute a bounding box over all objects so that we can know |
| 5838 | 5887 | ** how big to declare the SVG canvas */ |
| 5839 | 5888 | pik_bbox_init(&p->bbox); |
| 5840 | - for(i=0; i<pEList->n; i++){ | |
| 5841 | - PElem *pElem = pEList->a[i]; | |
| 5842 | - pik_bbox_addbox(&p->bbox, &pElem->bbox); | |
| 5843 | - | |
| 5844 | - /* Expand the bounding box to account for arrowheads on lines */ | |
| 5845 | - if( pElem->type->isLine && pElem->nPath>0 ){ | |
| 5846 | - if( pElem->larrow ){ | |
| 5847 | - pik_bbox_addellipse(&p->bbox, pElem->aPath[0].x, pElem->aPath[0].y, | |
| 5848 | - wArrow, wArrow); | |
| 5849 | - } | |
| 5850 | - if( pElem->rarrow ){ | |
| 5851 | - j = pElem->nPath-1; | |
| 5852 | - pik_bbox_addellipse(&p->bbox, pElem->aPath[j].x, pElem->aPath[j].y, | |
| 5853 | - wArrow, wArrow); | |
| 5854 | - } | |
| 5855 | - } | |
| 5856 | - } | |
| 5889 | + pik_bbox_add_elist(p, pEList, wArrow); | |
| 5857 | 5890 | |
| 5858 | 5891 | /* Expand the bounding box slightly to account for line thickness |
| 5859 | 5892 | ** and the optional "margin = EXPR" setting. */ |
| 5860 | 5893 | p->bbox.ne.x += margin; |
| 5861 | 5894 | p->bbox.ne.y += margin; |
| @@ -6451,6 +6484,6 @@ | ||
| 6451 | 6484 | printf("</body></html>\n"); |
| 6452 | 6485 | return 0; |
| 6453 | 6486 | } |
| 6454 | 6487 | #endif /* PIKCHR_SHELL */ |
| 6455 | 6488 | |
| 6456 | -#line 6481 "pikchr.c" | |
| 6489 | +#line 6514 "pikchr.c" | |
| 6457 | 6490 |
| --- src/pikchr.c | |
| +++ src/pikchr.c | |
| @@ -366,11 +366,11 @@ | |
| 366 | static void pik_append_xy(Pik*,const char*,PNum,PNum); |
| 367 | static void pik_append_dis(Pik*,const char*,PNum,const char*); |
| 368 | static void pik_append_arc(Pik*,PNum,PNum,PNum,PNum); |
| 369 | static void pik_append_clr(Pik*,const char*,PNum,const char*); |
| 370 | static void pik_append_style(Pik*,PElem*); |
| 371 | static void pik_append_txt(Pik*,PElem*); |
| 372 | static void pik_draw_arrowhead(Pik*,PPoint*pFrom,PPoint*pTo,PElem*); |
| 373 | static void pik_chop(Pik*,PPoint*pFrom,PPoint*pTo,PNum); |
| 374 | static void pik_error(Pik*,PToken*,const char*); |
| 375 | static void pik_elist_free(Pik*,PEList*); |
| 376 | static void pik_elem_free(Pik*,PElem*); |
| @@ -401,11 +401,11 @@ | |
| 401 | static PElem *pik_find_byname(Pik*,PElem*,PToken*); |
| 402 | static PPoint pik_place_of_elem(Pik*,PElem*,PToken*); |
| 403 | static int pik_bbox_isempty(PBox*); |
| 404 | static void pik_bbox_init(PBox*); |
| 405 | static void pik_bbox_addbox(PBox*,PBox*); |
| 406 | static void pik_bbox_addpt(PBox*,PPoint*); |
| 407 | static void pik_bbox_addellipse(PBox*,PNum x,PNum y,PNum rx,PNum ry); |
| 408 | static void pik_add_txt(Pik*,PToken*,int); |
| 409 | static int pik_text_length(const PToken *pToken); |
| 410 | static void pik_size_to_fit(Pik*,PToken*); |
| 411 | static int pik_text_position(Pik*,int,PToken*); |
| @@ -3308,11 +3308,11 @@ | |
| 3308 | pik_append_xy(p," ", t.x, t.y); |
| 3309 | pik_append(p,"\" ",2); |
| 3310 | pik_append_style(p,pElem); |
| 3311 | pik_append(p,"\" />\n", -1); |
| 3312 | |
| 3313 | pik_append_txt(p, pElem); |
| 3314 | } |
| 3315 | |
| 3316 | |
| 3317 | /* Methods for the "arrow" class */ |
| 3318 | static void arrowInit(Pik *p, PElem *pElem){ |
| @@ -3449,11 +3449,11 @@ | |
| 3449 | pik_append(p,"Z\" ",-1); |
| 3450 | } |
| 3451 | pik_append_style(p,pElem); |
| 3452 | pik_append(p,"\" />\n", -1); |
| 3453 | } |
| 3454 | pik_append_txt(p, pElem); |
| 3455 | } |
| 3456 | |
| 3457 | /* Methods for the "circle" class */ |
| 3458 | static void circleInit(Pik *p, PElem *pElem){ |
| 3459 | pElem->w = pik_value(p, "circlerad",9,0)*2; |
| @@ -3508,11 +3508,11 @@ | |
| 3508 | pik_append_y(p," cy=\"", pt.y, "\""); |
| 3509 | pik_append_dis(p," r=\"", r, "\" "); |
| 3510 | pik_append_style(p,pElem); |
| 3511 | pik_append(p,"\" />\n", -1); |
| 3512 | } |
| 3513 | pik_append_txt(p, pElem); |
| 3514 | } |
| 3515 | |
| 3516 | /* Methods for the "cylinder" class */ |
| 3517 | static void cylinderInit(Pik *p, PElem *pElem){ |
| 3518 | pElem->w = pik_value(p, "cylwid",6,0); |
| @@ -3533,11 +3533,11 @@ | |
| 3533 | pik_append_arc(p,w2,rad,pt.x+w2,pt.y+h2-rad); |
| 3534 | pik_append(p,"\" ",-1); |
| 3535 | pik_append_style(p,pElem); |
| 3536 | pik_append(p,"\" />\n", -1); |
| 3537 | } |
| 3538 | pik_append_txt(p, pElem); |
| 3539 | } |
| 3540 | static PPoint cylinderOffset(Pik *p, PElem *pElem, int cp){ |
| 3541 | PPoint pt; |
| 3542 | PNum w2 = pElem->w*0.5; |
| 3543 | PNum h1 = pElem->h*0.5; |
| @@ -3580,11 +3580,11 @@ | |
| 3580 | pik_append_y(p," cy=\"", pt.y, "\""); |
| 3581 | pik_append_dis(p," r=\"", r, "\""); |
| 3582 | pik_append_style(p,pElem); |
| 3583 | pik_append(p,"\" />\n", -1); |
| 3584 | } |
| 3585 | pik_append_txt(p, pElem); |
| 3586 | } |
| 3587 | |
| 3588 | |
| 3589 | |
| 3590 | /* Methods for the "ellipse" class */ |
| @@ -3636,11 +3636,11 @@ | |
| 3636 | pik_append_dis(p," rx=\"", w/2.0, "\""); |
| 3637 | pik_append_dis(p," ry=\"", h/2.0, "\" "); |
| 3638 | pik_append_style(p,pElem); |
| 3639 | pik_append(p,"\" />\n", -1); |
| 3640 | } |
| 3641 | pik_append_txt(p, pElem); |
| 3642 | } |
| 3643 | |
| 3644 | /* Methods for the "line" class */ |
| 3645 | static void lineInit(Pik *p, PElem *pElem){ |
| 3646 | pElem->w = pik_value(p, "linewid",7,0); |
| @@ -3670,11 +3670,11 @@ | |
| 3670 | } |
| 3671 | pik_append(p,"\" ",-1); |
| 3672 | pik_append_style(p,pElem); |
| 3673 | pik_append(p,"\" />\n", -1); |
| 3674 | } |
| 3675 | pik_append_txt(p, pElem); |
| 3676 | } |
| 3677 | |
| 3678 | /* Methods for the "move" class */ |
| 3679 | static void moveInit(Pik *p, PElem *pElem){ |
| 3680 | pElem->w = pik_value(p, "movewid",7,0); |
| @@ -3773,11 +3773,11 @@ | |
| 3773 | if( pElem->rarrow ){ |
| 3774 | pik_draw_arrowhead(p,&pElem->aPath[n-2],&pElem->aPath[n-1],pElem); |
| 3775 | } |
| 3776 | radiusPath(p,pElem,pElem->rad); |
| 3777 | } |
| 3778 | pik_append_txt(p, pElem); |
| 3779 | } |
| 3780 | |
| 3781 | |
| 3782 | /* Methods for the "text" class */ |
| 3783 | static void textInit(Pik *p, PElem *pElem){ |
| @@ -4229,13 +4229,17 @@ | |
| 4229 | } |
| 4230 | } |
| 4231 | } |
| 4232 | } |
| 4233 | |
| 4234 | /* Append multiple <text> SGV element for the text fields of the PElem |
| 4235 | */ |
| 4236 | static void pik_append_txt(Pik *p, PElem *pElem){ |
| 4237 | PNum dy; /* Half the height of a single line of text */ |
| 4238 | PNum dy2; /* Extra vertical space around the center */ |
| 4239 | int n, i, nz; |
| 4240 | PNum x, y, orig_y; |
| 4241 | const char *z; |
| @@ -4264,10 +4268,28 @@ | |
| 4264 | orig_y = y = pElem->ptAt.y; |
| 4265 | if( t->eCode & TP_ABOVE2 ) y += dy2 + 3*dy; |
| 4266 | if( t->eCode & TP_ABOVE ) y += dy2 + dy; |
| 4267 | if( t->eCode & TP_BELOW ) y -= dy2 + dy; |
| 4268 | if( t->eCode & TP_BELOW2 ) y -= dy2 + 3*dy; |
| 4269 | |
| 4270 | pik_append_x(p, "<text x=\"", x, "\""); |
| 4271 | pik_append_y(p, " y=\"", y, "\""); |
| 4272 | if( t->eCode & TP_RJUST ){ |
| 4273 | pik_append(p, " text-anchor=\"end\"", -1); |
| @@ -4442,20 +4464,22 @@ | |
| 4442 | } |
| 4443 | |
| 4444 | /* Enlarge the PBox of the first argument, if necessary, so that |
| 4445 | ** it contains the PPoint in the second argument |
| 4446 | */ |
| 4447 | static void pik_bbox_addpt(PBox *pA, PPoint *pPt){ |
| 4448 | if( pik_bbox_isempty(pA) ){ |
| 4449 | pA->ne = *pPt; |
| 4450 | pA->sw = *pPt; |
| 4451 | return; |
| 4452 | } |
| 4453 | if( pA->sw.x>pPt->x ) pA->sw.x = pPt->x; |
| 4454 | if( pA->sw.y>pPt->y ) pA->sw.y = pPt->y; |
| 4455 | if( pA->ne.x<pPt->x ) pA->ne.x = pPt->x; |
| 4456 | if( pA->ne.y<pPt->y ) pA->ne.y = pPt->y; |
| 4457 | } |
| 4458 | |
| 4459 | /* Enlarge the PBox so that it is able to contain an ellipse |
| 4460 | ** centered at x,y and with radiuses rx and ry. |
| 4461 | */ |
| @@ -5663,11 +5687,11 @@ | |
| 5663 | pElem->nPath = 0; |
| 5664 | }else{ |
| 5665 | pElem->nPath = p->nTPath; |
| 5666 | for(i=0; i<p->nTPath; i++){ |
| 5667 | pElem->aPath[i] = p->aTPath[i]; |
| 5668 | pik_bbox_addpt(&pElem->bbox, &pElem->aPath[i]); |
| 5669 | } |
| 5670 | } |
| 5671 | |
| 5672 | /* "chop" processing: |
| 5673 | ** If the line goes to the center of an object with an |
| @@ -5787,10 +5811,36 @@ | |
| 5787 | pik_elist_render(p, pElem->pSublist); |
| 5788 | } |
| 5789 | } |
| 5790 | }while( bMoreToDo ); |
| 5791 | } |
| 5792 | |
| 5793 | /* Recompute key layout parameters from variables. */ |
| 5794 | static void pik_compute_layout_settings(Pik *p){ |
| 5795 | PNum thickness; /* Line thickness */ |
| 5796 | PNum wArrow; /* Width of arrowheads */ |
| @@ -5814,11 +5864,10 @@ | |
| 5814 | |
| 5815 | /* Render a list of elements. Write the SVG into p->zOut. |
| 5816 | ** Delete the input element_list before returnning. |
| 5817 | */ |
| 5818 | static void pik_render(Pik *p, PEList *pEList){ |
| 5819 | int i, j; |
| 5820 | if( pEList==0 ) return; |
| 5821 | if( p->nErr==0 ){ |
| 5822 | PNum thickness; /* Stroke width */ |
| 5823 | PNum margin; /* Extra bounding box margin */ |
| 5824 | PNum leftmargin; /* Extra bounding box area on the left */ |
| @@ -5835,27 +5884,11 @@ | |
| 5835 | wArrow = p->wArrow*thickness; |
| 5836 | |
| 5837 | /* Compute a bounding box over all objects so that we can know |
| 5838 | ** how big to declare the SVG canvas */ |
| 5839 | pik_bbox_init(&p->bbox); |
| 5840 | for(i=0; i<pEList->n; i++){ |
| 5841 | PElem *pElem = pEList->a[i]; |
| 5842 | pik_bbox_addbox(&p->bbox, &pElem->bbox); |
| 5843 | |
| 5844 | /* Expand the bounding box to account for arrowheads on lines */ |
| 5845 | if( pElem->type->isLine && pElem->nPath>0 ){ |
| 5846 | if( pElem->larrow ){ |
| 5847 | pik_bbox_addellipse(&p->bbox, pElem->aPath[0].x, pElem->aPath[0].y, |
| 5848 | wArrow, wArrow); |
| 5849 | } |
| 5850 | if( pElem->rarrow ){ |
| 5851 | j = pElem->nPath-1; |
| 5852 | pik_bbox_addellipse(&p->bbox, pElem->aPath[j].x, pElem->aPath[j].y, |
| 5853 | wArrow, wArrow); |
| 5854 | } |
| 5855 | } |
| 5856 | } |
| 5857 | |
| 5858 | /* Expand the bounding box slightly to account for line thickness |
| 5859 | ** and the optional "margin = EXPR" setting. */ |
| 5860 | p->bbox.ne.x += margin; |
| 5861 | p->bbox.ne.y += margin; |
| @@ -6451,6 +6484,6 @@ | |
| 6451 | printf("</body></html>\n"); |
| 6452 | return 0; |
| 6453 | } |
| 6454 | #endif /* PIKCHR_SHELL */ |
| 6455 | |
| 6456 | #line 6481 "pikchr.c" |
| 6457 |
| --- src/pikchr.c | |
| +++ src/pikchr.c | |
| @@ -366,11 +366,11 @@ | |
| 366 | static void pik_append_xy(Pik*,const char*,PNum,PNum); |
| 367 | static void pik_append_dis(Pik*,const char*,PNum,const char*); |
| 368 | static void pik_append_arc(Pik*,PNum,PNum,PNum,PNum); |
| 369 | static void pik_append_clr(Pik*,const char*,PNum,const char*); |
| 370 | static void pik_append_style(Pik*,PElem*); |
| 371 | static void pik_append_txt(Pik*,PElem*, PBox*); |
| 372 | static void pik_draw_arrowhead(Pik*,PPoint*pFrom,PPoint*pTo,PElem*); |
| 373 | static void pik_chop(Pik*,PPoint*pFrom,PPoint*pTo,PNum); |
| 374 | static void pik_error(Pik*,PToken*,const char*); |
| 375 | static void pik_elist_free(Pik*,PEList*); |
| 376 | static void pik_elem_free(Pik*,PElem*); |
| @@ -401,11 +401,11 @@ | |
| 401 | static PElem *pik_find_byname(Pik*,PElem*,PToken*); |
| 402 | static PPoint pik_place_of_elem(Pik*,PElem*,PToken*); |
| 403 | static int pik_bbox_isempty(PBox*); |
| 404 | static void pik_bbox_init(PBox*); |
| 405 | static void pik_bbox_addbox(PBox*,PBox*); |
| 406 | static void pik_bbox_add_xy(PBox*,PNum,PNum); |
| 407 | static void pik_bbox_addellipse(PBox*,PNum x,PNum y,PNum rx,PNum ry); |
| 408 | static void pik_add_txt(Pik*,PToken*,int); |
| 409 | static int pik_text_length(const PToken *pToken); |
| 410 | static void pik_size_to_fit(Pik*,PToken*); |
| 411 | static int pik_text_position(Pik*,int,PToken*); |
| @@ -3308,11 +3308,11 @@ | |
| 3308 | pik_append_xy(p," ", t.x, t.y); |
| 3309 | pik_append(p,"\" ",2); |
| 3310 | pik_append_style(p,pElem); |
| 3311 | pik_append(p,"\" />\n", -1); |
| 3312 | |
| 3313 | pik_append_txt(p, pElem, 0); |
| 3314 | } |
| 3315 | |
| 3316 | |
| 3317 | /* Methods for the "arrow" class */ |
| 3318 | static void arrowInit(Pik *p, PElem *pElem){ |
| @@ -3449,11 +3449,11 @@ | |
| 3449 | pik_append(p,"Z\" ",-1); |
| 3450 | } |
| 3451 | pik_append_style(p,pElem); |
| 3452 | pik_append(p,"\" />\n", -1); |
| 3453 | } |
| 3454 | pik_append_txt(p, pElem, 0); |
| 3455 | } |
| 3456 | |
| 3457 | /* Methods for the "circle" class */ |
| 3458 | static void circleInit(Pik *p, PElem *pElem){ |
| 3459 | pElem->w = pik_value(p, "circlerad",9,0)*2; |
| @@ -3508,11 +3508,11 @@ | |
| 3508 | pik_append_y(p," cy=\"", pt.y, "\""); |
| 3509 | pik_append_dis(p," r=\"", r, "\" "); |
| 3510 | pik_append_style(p,pElem); |
| 3511 | pik_append(p,"\" />\n", -1); |
| 3512 | } |
| 3513 | pik_append_txt(p, pElem, 0); |
| 3514 | } |
| 3515 | |
| 3516 | /* Methods for the "cylinder" class */ |
| 3517 | static void cylinderInit(Pik *p, PElem *pElem){ |
| 3518 | pElem->w = pik_value(p, "cylwid",6,0); |
| @@ -3533,11 +3533,11 @@ | |
| 3533 | pik_append_arc(p,w2,rad,pt.x+w2,pt.y+h2-rad); |
| 3534 | pik_append(p,"\" ",-1); |
| 3535 | pik_append_style(p,pElem); |
| 3536 | pik_append(p,"\" />\n", -1); |
| 3537 | } |
| 3538 | pik_append_txt(p, pElem, 0); |
| 3539 | } |
| 3540 | static PPoint cylinderOffset(Pik *p, PElem *pElem, int cp){ |
| 3541 | PPoint pt; |
| 3542 | PNum w2 = pElem->w*0.5; |
| 3543 | PNum h1 = pElem->h*0.5; |
| @@ -3580,11 +3580,11 @@ | |
| 3580 | pik_append_y(p," cy=\"", pt.y, "\""); |
| 3581 | pik_append_dis(p," r=\"", r, "\""); |
| 3582 | pik_append_style(p,pElem); |
| 3583 | pik_append(p,"\" />\n", -1); |
| 3584 | } |
| 3585 | pik_append_txt(p, pElem, 0); |
| 3586 | } |
| 3587 | |
| 3588 | |
| 3589 | |
| 3590 | /* Methods for the "ellipse" class */ |
| @@ -3636,11 +3636,11 @@ | |
| 3636 | pik_append_dis(p," rx=\"", w/2.0, "\""); |
| 3637 | pik_append_dis(p," ry=\"", h/2.0, "\" "); |
| 3638 | pik_append_style(p,pElem); |
| 3639 | pik_append(p,"\" />\n", -1); |
| 3640 | } |
| 3641 | pik_append_txt(p, pElem, 0); |
| 3642 | } |
| 3643 | |
| 3644 | /* Methods for the "line" class */ |
| 3645 | static void lineInit(Pik *p, PElem *pElem){ |
| 3646 | pElem->w = pik_value(p, "linewid",7,0); |
| @@ -3670,11 +3670,11 @@ | |
| 3670 | } |
| 3671 | pik_append(p,"\" ",-1); |
| 3672 | pik_append_style(p,pElem); |
| 3673 | pik_append(p,"\" />\n", -1); |
| 3674 | } |
| 3675 | pik_append_txt(p, pElem, 0); |
| 3676 | } |
| 3677 | |
| 3678 | /* Methods for the "move" class */ |
| 3679 | static void moveInit(Pik *p, PElem *pElem){ |
| 3680 | pElem->w = pik_value(p, "movewid",7,0); |
| @@ -3773,11 +3773,11 @@ | |
| 3773 | if( pElem->rarrow ){ |
| 3774 | pik_draw_arrowhead(p,&pElem->aPath[n-2],&pElem->aPath[n-1],pElem); |
| 3775 | } |
| 3776 | radiusPath(p,pElem,pElem->rad); |
| 3777 | } |
| 3778 | pik_append_txt(p, pElem, 0); |
| 3779 | } |
| 3780 | |
| 3781 | |
| 3782 | /* Methods for the "text" class */ |
| 3783 | static void textInit(Pik *p, PElem *pElem){ |
| @@ -4229,13 +4229,17 @@ | |
| 4229 | } |
| 4230 | } |
| 4231 | } |
| 4232 | } |
| 4233 | |
| 4234 | /* Append multiple <text> SGV element for the text fields of the PElem. |
| 4235 | ** |
| 4236 | ** Or, if pBox!=NULL, then do not actually do any output. Instead |
| 4237 | ** guess at how large the various <text> elements would be and where |
| 4238 | ** the will be located and expand the pBox to include them. |
| 4239 | */ |
| 4240 | static void pik_append_txt(Pik *p, PElem *pElem, PBox *pBox){ |
| 4241 | PNum dy; /* Half the height of a single line of text */ |
| 4242 | PNum dy2; /* Extra vertical space around the center */ |
| 4243 | int n, i, nz; |
| 4244 | PNum x, y, orig_y; |
| 4245 | const char *z; |
| @@ -4264,10 +4268,28 @@ | |
| 4268 | orig_y = y = pElem->ptAt.y; |
| 4269 | if( t->eCode & TP_ABOVE2 ) y += dy2 + 3*dy; |
| 4270 | if( t->eCode & TP_ABOVE ) y += dy2 + dy; |
| 4271 | if( t->eCode & TP_BELOW ) y -= dy2 + dy; |
| 4272 | if( t->eCode & TP_BELOW2 ) y -= dy2 + 3*dy; |
| 4273 | |
| 4274 | if( pBox!=0 ){ |
| 4275 | /* If pBox is not NULL, do not draw any <text>. Instead, just expand |
| 4276 | ** pBox to include the text */ |
| 4277 | PNum cw = pik_text_length(t)*p->charWidth; |
| 4278 | PNum ch = p->charHeight*0.5; |
| 4279 | if( t->eCode & TP_RJUST ){ |
| 4280 | pik_bbox_add_xy(pBox, x, y-ch); |
| 4281 | pik_bbox_add_xy(pBox, x-cw, y+ch); |
| 4282 | }else if( t->eCode & TP_LJUST ){ |
| 4283 | pik_bbox_add_xy(pBox, x, y-ch); |
| 4284 | pik_bbox_add_xy(pBox, x+cw, y+ch); |
| 4285 | }else{ |
| 4286 | pik_bbox_add_xy(pBox, x+cw/2, y+ch); |
| 4287 | pik_bbox_add_xy(pBox, x-cw/2, y-ch); |
| 4288 | } |
| 4289 | continue; |
| 4290 | } |
| 4291 | |
| 4292 | pik_append_x(p, "<text x=\"", x, "\""); |
| 4293 | pik_append_y(p, " y=\"", y, "\""); |
| 4294 | if( t->eCode & TP_RJUST ){ |
| 4295 | pik_append(p, " text-anchor=\"end\"", -1); |
| @@ -4442,20 +4464,22 @@ | |
| 4464 | } |
| 4465 | |
| 4466 | /* Enlarge the PBox of the first argument, if necessary, so that |
| 4467 | ** it contains the PPoint in the second argument |
| 4468 | */ |
| 4469 | static void pik_bbox_add_xy(PBox *pA, PNum x, PNum y){ |
| 4470 | if( pik_bbox_isempty(pA) ){ |
| 4471 | pA->ne.x = x; |
| 4472 | pA->ne.y = y; |
| 4473 | pA->sw.x = x; |
| 4474 | pA->sw.y = y; |
| 4475 | return; |
| 4476 | } |
| 4477 | if( pA->sw.x>x ) pA->sw.x = x; |
| 4478 | if( pA->sw.y>y ) pA->sw.y = y; |
| 4479 | if( pA->ne.x<x ) pA->ne.x = x; |
| 4480 | if( pA->ne.y<y ) pA->ne.y = y; |
| 4481 | } |
| 4482 | |
| 4483 | /* Enlarge the PBox so that it is able to contain an ellipse |
| 4484 | ** centered at x,y and with radiuses rx and ry. |
| 4485 | */ |
| @@ -5663,11 +5687,11 @@ | |
| 5687 | pElem->nPath = 0; |
| 5688 | }else{ |
| 5689 | pElem->nPath = p->nTPath; |
| 5690 | for(i=0; i<p->nTPath; i++){ |
| 5691 | pElem->aPath[i] = p->aTPath[i]; |
| 5692 | pik_bbox_add_xy(&pElem->bbox, pElem->aPath[i].x, pElem->aPath[i].y); |
| 5693 | } |
| 5694 | } |
| 5695 | |
| 5696 | /* "chop" processing: |
| 5697 | ** If the line goes to the center of an object with an |
| @@ -5787,10 +5811,36 @@ | |
| 5811 | pik_elist_render(p, pElem->pSublist); |
| 5812 | } |
| 5813 | } |
| 5814 | }while( bMoreToDo ); |
| 5815 | } |
| 5816 | |
| 5817 | /* Add all elements of the list pEList to the bounding box |
| 5818 | */ |
| 5819 | static void pik_bbox_add_elist(Pik *p, PEList *pEList, PNum wArrow){ |
| 5820 | int i; |
| 5821 | for(i=0; i<pEList->n; i++){ |
| 5822 | PElem *pElem = pEList->a[i]; |
| 5823 | pik_bbox_addbox(&p->bbox, &pElem->bbox); |
| 5824 | pik_append_txt(p, pElem, &p->bbox); |
| 5825 | if( pElem->pSublist ) pik_bbox_add_elist(p, pElem->pSublist, wArrow); |
| 5826 | |
| 5827 | |
| 5828 | /* Expand the bounding box to account for arrowheads on lines */ |
| 5829 | if( pElem->type->isLine && pElem->nPath>0 ){ |
| 5830 | if( pElem->larrow ){ |
| 5831 | pik_bbox_addellipse(&p->bbox, pElem->aPath[0].x, pElem->aPath[0].y, |
| 5832 | wArrow, wArrow); |
| 5833 | } |
| 5834 | if( pElem->rarrow ){ |
| 5835 | int j = pElem->nPath-1; |
| 5836 | pik_bbox_addellipse(&p->bbox, pElem->aPath[j].x, pElem->aPath[j].y, |
| 5837 | wArrow, wArrow); |
| 5838 | } |
| 5839 | } |
| 5840 | } |
| 5841 | } |
| 5842 | |
| 5843 | /* Recompute key layout parameters from variables. */ |
| 5844 | static void pik_compute_layout_settings(Pik *p){ |
| 5845 | PNum thickness; /* Line thickness */ |
| 5846 | PNum wArrow; /* Width of arrowheads */ |
| @@ -5814,11 +5864,10 @@ | |
| 5864 | |
| 5865 | /* Render a list of elements. Write the SVG into p->zOut. |
| 5866 | ** Delete the input element_list before returnning. |
| 5867 | */ |
| 5868 | static void pik_render(Pik *p, PEList *pEList){ |
| 5869 | if( pEList==0 ) return; |
| 5870 | if( p->nErr==0 ){ |
| 5871 | PNum thickness; /* Stroke width */ |
| 5872 | PNum margin; /* Extra bounding box margin */ |
| 5873 | PNum leftmargin; /* Extra bounding box area on the left */ |
| @@ -5835,27 +5884,11 @@ | |
| 5884 | wArrow = p->wArrow*thickness; |
| 5885 | |
| 5886 | /* Compute a bounding box over all objects so that we can know |
| 5887 | ** how big to declare the SVG canvas */ |
| 5888 | pik_bbox_init(&p->bbox); |
| 5889 | pik_bbox_add_elist(p, pEList, wArrow); |
| 5890 | |
| 5891 | /* Expand the bounding box slightly to account for line thickness |
| 5892 | ** and the optional "margin = EXPR" setting. */ |
| 5893 | p->bbox.ne.x += margin; |
| 5894 | p->bbox.ne.y += margin; |
| @@ -6451,6 +6484,6 @@ | |
| 6484 | printf("</body></html>\n"); |
| 6485 | return 0; |
| 6486 | } |
| 6487 | #endif /* PIKCHR_SHELL */ |
| 6488 | |
| 6489 | #line 6514 "pikchr.c" |
| 6490 |