Fossil SCM

Update to a new version of pikchr.c with improved text bounding box computation.

drh 2020-09-11 01:37 trunk
Commit 1f2b6cedadf4e82a80720e4f227343a568f2272cc04d976c0195f14092da68b6
1 file changed +72 -39
+72 -39
--- src/pikchr.c
+++ src/pikchr.c
@@ -366,11 +366,11 @@
366366
static void pik_append_xy(Pik*,const char*,PNum,PNum);
367367
static void pik_append_dis(Pik*,const char*,PNum,const char*);
368368
static void pik_append_arc(Pik*,PNum,PNum,PNum,PNum);
369369
static void pik_append_clr(Pik*,const char*,PNum,const char*);
370370
static void pik_append_style(Pik*,PElem*);
371
-static void pik_append_txt(Pik*,PElem*);
371
+static void pik_append_txt(Pik*,PElem*, PBox*);
372372
static void pik_draw_arrowhead(Pik*,PPoint*pFrom,PPoint*pTo,PElem*);
373373
static void pik_chop(Pik*,PPoint*pFrom,PPoint*pTo,PNum);
374374
static void pik_error(Pik*,PToken*,const char*);
375375
static void pik_elist_free(Pik*,PEList*);
376376
static void pik_elem_free(Pik*,PElem*);
@@ -401,11 +401,11 @@
401401
static PElem *pik_find_byname(Pik*,PElem*,PToken*);
402402
static PPoint pik_place_of_elem(Pik*,PElem*,PToken*);
403403
static int pik_bbox_isempty(PBox*);
404404
static void pik_bbox_init(PBox*);
405405
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);
407407
static void pik_bbox_addellipse(PBox*,PNum x,PNum y,PNum rx,PNum ry);
408408
static void pik_add_txt(Pik*,PToken*,int);
409409
static int pik_text_length(const PToken *pToken);
410410
static void pik_size_to_fit(Pik*,PToken*);
411411
static int pik_text_position(Pik*,int,PToken*);
@@ -3308,11 +3308,11 @@
33083308
pik_append_xy(p," ", t.x, t.y);
33093309
pik_append(p,"\" ",2);
33103310
pik_append_style(p,pElem);
33113311
pik_append(p,"\" />\n", -1);
33123312
3313
- pik_append_txt(p, pElem);
3313
+ pik_append_txt(p, pElem, 0);
33143314
}
33153315
33163316
33173317
/* Methods for the "arrow" class */
33183318
static void arrowInit(Pik *p, PElem *pElem){
@@ -3449,11 +3449,11 @@
34493449
pik_append(p,"Z\" ",-1);
34503450
}
34513451
pik_append_style(p,pElem);
34523452
pik_append(p,"\" />\n", -1);
34533453
}
3454
- pik_append_txt(p, pElem);
3454
+ pik_append_txt(p, pElem, 0);
34553455
}
34563456
34573457
/* Methods for the "circle" class */
34583458
static void circleInit(Pik *p, PElem *pElem){
34593459
pElem->w = pik_value(p, "circlerad",9,0)*2;
@@ -3508,11 +3508,11 @@
35083508
pik_append_y(p," cy=\"", pt.y, "\"");
35093509
pik_append_dis(p," r=\"", r, "\" ");
35103510
pik_append_style(p,pElem);
35113511
pik_append(p,"\" />\n", -1);
35123512
}
3513
- pik_append_txt(p, pElem);
3513
+ pik_append_txt(p, pElem, 0);
35143514
}
35153515
35163516
/* Methods for the "cylinder" class */
35173517
static void cylinderInit(Pik *p, PElem *pElem){
35183518
pElem->w = pik_value(p, "cylwid",6,0);
@@ -3533,11 +3533,11 @@
35333533
pik_append_arc(p,w2,rad,pt.x+w2,pt.y+h2-rad);
35343534
pik_append(p,"\" ",-1);
35353535
pik_append_style(p,pElem);
35363536
pik_append(p,"\" />\n", -1);
35373537
}
3538
- pik_append_txt(p, pElem);
3538
+ pik_append_txt(p, pElem, 0);
35393539
}
35403540
static PPoint cylinderOffset(Pik *p, PElem *pElem, int cp){
35413541
PPoint pt;
35423542
PNum w2 = pElem->w*0.5;
35433543
PNum h1 = pElem->h*0.5;
@@ -3580,11 +3580,11 @@
35803580
pik_append_y(p," cy=\"", pt.y, "\"");
35813581
pik_append_dis(p," r=\"", r, "\"");
35823582
pik_append_style(p,pElem);
35833583
pik_append(p,"\" />\n", -1);
35843584
}
3585
- pik_append_txt(p, pElem);
3585
+ pik_append_txt(p, pElem, 0);
35863586
}
35873587
35883588
35893589
35903590
/* Methods for the "ellipse" class */
@@ -3636,11 +3636,11 @@
36363636
pik_append_dis(p," rx=\"", w/2.0, "\"");
36373637
pik_append_dis(p," ry=\"", h/2.0, "\" ");
36383638
pik_append_style(p,pElem);
36393639
pik_append(p,"\" />\n", -1);
36403640
}
3641
- pik_append_txt(p, pElem);
3641
+ pik_append_txt(p, pElem, 0);
36423642
}
36433643
36443644
/* Methods for the "line" class */
36453645
static void lineInit(Pik *p, PElem *pElem){
36463646
pElem->w = pik_value(p, "linewid",7,0);
@@ -3670,11 +3670,11 @@
36703670
}
36713671
pik_append(p,"\" ",-1);
36723672
pik_append_style(p,pElem);
36733673
pik_append(p,"\" />\n", -1);
36743674
}
3675
- pik_append_txt(p, pElem);
3675
+ pik_append_txt(p, pElem, 0);
36763676
}
36773677
36783678
/* Methods for the "move" class */
36793679
static void moveInit(Pik *p, PElem *pElem){
36803680
pElem->w = pik_value(p, "movewid",7,0);
@@ -3773,11 +3773,11 @@
37733773
if( pElem->rarrow ){
37743774
pik_draw_arrowhead(p,&pElem->aPath[n-2],&pElem->aPath[n-1],pElem);
37753775
}
37763776
radiusPath(p,pElem,pElem->rad);
37773777
}
3778
- pik_append_txt(p, pElem);
3778
+ pik_append_txt(p, pElem, 0);
37793779
}
37803780
37813781
37823782
/* Methods for the "text" class */
37833783
static void textInit(Pik *p, PElem *pElem){
@@ -4229,13 +4229,17 @@
42294229
}
42304230
}
42314231
}
42324232
}
42334233
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.
42354239
*/
4236
-static void pik_append_txt(Pik *p, PElem *pElem){
4240
+static void pik_append_txt(Pik *p, PElem *pElem, PBox *pBox){
42374241
PNum dy; /* Half the height of a single line of text */
42384242
PNum dy2; /* Extra vertical space around the center */
42394243
int n, i, nz;
42404244
PNum x, y, orig_y;
42414245
const char *z;
@@ -4264,10 +4268,28 @@
42644268
orig_y = y = pElem->ptAt.y;
42654269
if( t->eCode & TP_ABOVE2 ) y += dy2 + 3*dy;
42664270
if( t->eCode & TP_ABOVE ) y += dy2 + dy;
42674271
if( t->eCode & TP_BELOW ) y -= dy2 + dy;
42684272
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
+ }
42694291
42704292
pik_append_x(p, "<text x=\"", x, "\"");
42714293
pik_append_y(p, " y=\"", y, "\"");
42724294
if( t->eCode & TP_RJUST ){
42734295
pik_append(p, " text-anchor=\"end\"", -1);
@@ -4442,20 +4464,22 @@
44424464
}
44434465
44444466
/* Enlarge the PBox of the first argument, if necessary, so that
44454467
** it contains the PPoint in the second argument
44464468
*/
4447
-static void pik_bbox_addpt(PBox *pA, PPoint *pPt){
4469
+static void pik_bbox_add_xy(PBox *pA, PNum x, PNum y){
44484470
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;
44514475
return;
44524476
}
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;
44574481
}
44584482
44594483
/* Enlarge the PBox so that it is able to contain an ellipse
44604484
** centered at x,y and with radiuses rx and ry.
44614485
*/
@@ -5663,11 +5687,11 @@
56635687
pElem->nPath = 0;
56645688
}else{
56655689
pElem->nPath = p->nTPath;
56665690
for(i=0; i<p->nTPath; i++){
56675691
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);
56695693
}
56705694
}
56715695
56725696
/* "chop" processing:
56735697
** If the line goes to the center of an object with an
@@ -5787,10 +5811,36 @@
57875811
pik_elist_render(p, pElem->pSublist);
57885812
}
57895813
}
57905814
}while( bMoreToDo );
57915815
}
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
+}
57925842
57935843
/* Recompute key layout parameters from variables. */
57945844
static void pik_compute_layout_settings(Pik *p){
57955845
PNum thickness; /* Line thickness */
57965846
PNum wArrow; /* Width of arrowheads */
@@ -5814,11 +5864,10 @@
58145864
58155865
/* Render a list of elements. Write the SVG into p->zOut.
58165866
** Delete the input element_list before returnning.
58175867
*/
58185868
static void pik_render(Pik *p, PEList *pEList){
5819
- int i, j;
58205869
if( pEList==0 ) return;
58215870
if( p->nErr==0 ){
58225871
PNum thickness; /* Stroke width */
58235872
PNum margin; /* Extra bounding box margin */
58245873
PNum leftmargin; /* Extra bounding box area on the left */
@@ -5835,27 +5884,11 @@
58355884
wArrow = p->wArrow*thickness;
58365885
58375886
/* Compute a bounding box over all objects so that we can know
58385887
** how big to declare the SVG canvas */
58395888
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);
58575890
58585891
/* Expand the bounding box slightly to account for line thickness
58595892
** and the optional "margin = EXPR" setting. */
58605893
p->bbox.ne.x += margin;
58615894
p->bbox.ne.y += margin;
@@ -6451,6 +6484,6 @@
64516484
printf("</body></html>\n");
64526485
return 0;
64536486
}
64546487
#endif /* PIKCHR_SHELL */
64556488
6456
-#line 6481 "pikchr.c"
6489
+#line 6514 "pikchr.c"
64576490
--- 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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button