1 #   include	"docLayoutConfig.h"
2 
3 #   include	"docDraw.h"
4 #   include	<docPageGrid.h>
5 #   include	<docTreeType.h>
6 #   include	<docTreeNode.h>
7 #   include	<docNodeTree.h>
8 #   include	<docTextLine.h>
9 #   include	"docParagraphLayout.h"
10 #   include	<docTextParticule.h>
11 
12 #   include	<appDebugon.h>
13 
14 /************************************************************************/
15 /*									*/
16 /*  Paragraph drawing machinery.					*/
17 /*									*/
18 /************************************************************************/
19 
20 /************************************************************************/
21 /*									*/
22 /*  Draw paragraph borders and shading.					*/
23 /*									*/
24 /************************************************************************/
25 
docDrawParaOrnaments(void * through,const ParagraphDrawingStrip * pds,const BufferItem * paraNode,const ParagraphFrame * pf,DrawingContext * dc,const BlockOrigin * bo)26 static int docDrawParaOrnaments( void *				through,
27 				const ParagraphDrawingStrip *	pds,
28 				const BufferItem *		paraNode,
29 				const ParagraphFrame *		pf,
30 				DrawingContext *		dc,
31 				const BlockOrigin *		bo )
32     {
33     const LayoutContext *	lc= &(dc->dcLayoutContext);
34     const BufferDocument *	bd= lc->lcDocument;
35 
36     LayoutPosition		lpTop;
37     LayoutPosition		lpBelow;
38 
39     BlockOrnaments		ornaments;
40     DocumentRectangle		drPara;
41     DocumentRectangle		drOutside;
42     DocumentRectangle		drInside;
43 
44     docInitBlockOrnaments( &ornaments );
45 
46     drPara= pf->pfParaContentRect;
47     if  ( paraNode->biParaFirstIndentTwips < 0 )
48 	{ drPara.drX0 += paraNode->biParaFirstIndentTwips;	}
49 
50     docShiftPosition( &lpTop, bo, &(pds->pdsShadeTop) );
51     docShiftPosition( &lpBelow, bo, &(pds->pdsShadeBelow) );
52 
53     drPara.drY0= lpTop.lpPageYTwips;
54     drPara.drY1= lpBelow.lpPageYTwips;
55 
56     if  ( paraNode->biParaTableNesting > 0 )
57 	{
58 	const BufferItem *	rowBi= docGetRowNode( (BufferItem *)paraNode );
59 
60 	if  ( ! rowBi )
61 	    { XDEB(rowBi);	}
62 	else{
63 	    int	x0= pf->pfParaContentRect.drX0- rowBi->biRowHalfGapWidthTwips;
64 	    int	x1= pf->pfParaContentRect.drX1+ rowBi->biRowHalfGapWidthTwips;
65 
66 	    if  ( drPara.drX0 < x0 )
67 		{ drPara.drX0=  x0;	}
68 	    if  ( drPara.drX1 > x1 )
69 		{ drPara.drX1=  x1;	}
70 	    }
71 	}
72 
73     docGetParaOrnaments( &ornaments, &drOutside, &drInside, &drPara,
74 			bd, paraNode, pds->pdsAtParaTop, pds->pdsAtParaBottom );
75 
76     if  ( (*dc->dcDrawOrnaments)( &ornaments, lpTop.lpPage,
77 						&drOutside, &drInside,
78 						through, dc ) )
79 	{ LDEB(1); return -1;	}
80 
81     return 0;
82     }
83 
84 /************************************************************************/
85 /*									*/
86 /*  Count the number of lines that fit on the current page.		*/
87 /*									*/
88 /************************************************************************/
89 
docDelimitParagraphDrawingStrip(ParagraphDrawingStrip * pds,const BufferItem * paraNode,int countAfter,const LayoutPosition * lpShadeTop,int lineFrom,const LayoutPosition * lpThisFrame,const BlockOrigin * bo)90 static int docDelimitParagraphDrawingStrip(
91 			ParagraphDrawingStrip *		pds,
92 			const BufferItem *		paraNode,
93 			int				countAfter,
94 			const LayoutPosition *		lpShadeTop,
95 			int				lineFrom,
96 			const LayoutPosition *		lpThisFrame,
97 			const BlockOrigin *		bo )
98     {
99     const TextLine *	tl;
100     LayoutPosition	lp;
101 
102     int			line= lineFrom;
103     int			atTop= lineFrom == 0;
104     int			atBottom= 0;
105     int			afterPageBreak= 0;
106 
107     LayoutPosition	lpBelow= *lpShadeTop;
108 
109     tl= paraNode->biParaLines+ line;
110     while( line < paraNode->biParaLineCount )
111 	{
112 	docShiftPosition( &lp, bo, &(tl->tlTopPosition) );
113 
114 	if  ( DOC_COLUMN_AFTER( &lp, lpThisFrame ) )
115 	    { break;	}
116 	if  ( DOC_COLUMN_AFTER( lpThisFrame, &lp ) )
117 	    { line++; tl++; continue;	}
118 
119 	lp.lpPageYTwips += tl->tlLineStride;
120 	lp.lpAtTopOfColumn= 0;
121 
122 	docLayoutPushBottomDown( &lpBelow, &lp );
123 
124 	afterPageBreak= paraNode->biParaParticules[
125 		    tl->tlFirstParticule+ tl->tlParticuleCount -1].tpKind ==
126 		    DOCkindPAGEBREAK;
127 
128 	line++; tl++;
129 	}
130 
131     if  ( line == paraNode->biParaLineCount )
132 	{
133 	if  ( ! afterPageBreak )
134 	    {
135 	    lp= paraNode->biBelowPosition;
136 
137 	    if  ( ! countAfter )
138 		{ lp.lpPageYTwips -= paraNode->biParaSpaceAfterTwips;	}
139 
140 	    docLayoutPushBottomDownShifted( &lpBelow, &lp, bo );
141 	    }
142 
143 	atBottom= 1;
144 	}
145 
146     pds->pdsLineFrom= lineFrom;
147     pds->pdsLineUpto= line;
148     pds->pdsAtParaTop= atTop;
149     pds->pdsAtParaBottom= atBottom;
150 
151     pds->pdsShadeTop= *lpShadeTop;
152     pds->pdsShadeBelow= lpBelow;
153 
154     return 0;
155     }
156 
157 /************************************************************************/
158 
docDrawParagraphStrip(void * through,ParagraphDrawingStrip * pds,BufferItem * paraNode,int countAfter,const LayoutPosition * lpShadeTop,int lineFrom,const ParagraphFrame * pf,DrawingContext * dc,const LayoutPosition * lpThisFrame,const BlockOrigin * bo)159 int docDrawParagraphStrip(		void *			through,
160 					ParagraphDrawingStrip *	pds,
161 					BufferItem *		paraNode,
162 					int			countAfter,
163 					const LayoutPosition *	lpShadeTop,
164 					int			lineFrom,
165 					const ParagraphFrame *	pf,
166 					DrawingContext *	dc,
167 					const LayoutPosition *	lpThisFrame,
168 					const BlockOrigin *	bo )
169     {
170     if  ( docDelimitParagraphDrawingStrip( pds, paraNode, countAfter,
171 				    lpShadeTop, lineFrom, lpThisFrame, bo ) )
172 	{ LDEB(1); return -1;	}
173 
174     if  ( pds->pdsLineUpto > lineFrom && dc->dcDrawOrnaments )
175 	{
176 	if  ( docDrawParaOrnaments( through, pds, paraNode, pf, dc, bo ) )
177 	    { LDEB(1); return -1;	}
178 	}
179 
180     if  ( docDrawTextLines( through, pds, paraNode, pf, dc, bo ) )
181 	{ LDEB(lpThisFrame->lpPage); return -1;	}
182 
183     return 0;
184     }
185 
186 /************************************************************************/
187 /*									*/
188 /*  Print a node in the BufferItem hierarchy.				*/
189 /*									*/
190 /*  1)  The last page is finished by the caller.			*/
191 /*									*/
192 /************************************************************************/
193 
docDrawParaNode(LayoutPosition * lpBelow,BufferItem * paraNode,void * through,DrawingContext * dc,const BlockOrigin * bo)194 int docDrawParaNode(		LayoutPosition *		lpBelow,
195 				BufferItem *			paraNode,
196 				void *				through,
197 				DrawingContext *		dc,
198 				const BlockOrigin *		bo )
199     {
200     int				rval= 0;
201     ParagraphFrame		pf;
202     int				line= 0;
203 
204     const LayoutContext *	lc= &(dc->dcLayoutContext);
205     BufferDocument *		bd= lc->lcDocument;
206 
207     BlockFrame			bf;
208     LayoutPosition		lpTop;
209     LayoutPosition		lpShadeTop;
210 
211     docLayoutInitBlockFrame( &bf );
212     docParaBlockFrameTwips( &bf, paraNode, bd, paraNode->biTopPosition.lpPage,
213 					    paraNode->biTopPosition.lpColumn );
214 
215     docParagraphFrameTwips( &pf, &bf, paraNode );
216 
217     docShiftPosition( &lpTop, bo, &(paraNode->biTopPosition) );
218     lpShadeTop= lpTop;
219 
220     if  ( ! lpShadeTop.lpAtTopOfColumn )
221 	{ lpShadeTop.lpPageYTwips += paraNode->biParaSpaceBeforeTwips; }
222 
223     while( line < paraNode->biParaLineCount )
224 	{
225 	const int		countAfter= 0;
226 
227 	ParagraphDrawingStrip	pds;
228 
229 	if  ( docDrawParagraphStrip( through, &pds, paraNode, countAfter,
230 			    &lpShadeTop, line, &pf, dc, &lpTop, bo ) )
231 	    { LDEB(line); rval= -1; goto ready;	}
232 
233 	line= pds.pdsLineUpto;
234 	if  ( lpBelow )
235 	    {
236 	    docLayoutPushBottomDown( lpBelow, &(pds.pdsShadeBelow) );
237 	    }
238 
239 	/*  1  */
240 if  ( paraNode->biTreeType == DOCinSHPTXT )
241     { break;	}
242 
243 	if  ( DOC_COLUMN_AFTER( &(paraNode->biBelowPosition), &lpTop ) )
244 	    {
245 	    int			ret;
246 	    BufferItem *	bodyNode= paraNode;
247 
248 	    if  ( paraNode->biTreeType != DOCinBODY )
249 		{
250 		bodyNode= docGetBodySectNode( paraNode, bd );
251 		if  ( ! bodyNode )
252 		    { XDEB(bodyNode); return -1;	}
253 		}
254 
255 	    ret= docDrawToNextColumn( bodyNode, bodyNode,
256 					    through, &lpTop, &bf, dc );
257 	    if  ( ret < 0 )
258 		{
259 		SLDEB(docLevelStr(paraNode->biLevel),ret);
260 		rval= -1; goto ready;
261 		}
262 	    if  ( ret > 0 )
263 		{ break;						}
264 
265 	    docParagraphFrameTwips( &pf, &bf, paraNode );
266 	    lpShadeTop= lpTop;
267 	    }
268 	}
269 
270     if  ( lpBelow && line >= paraNode->biParaLineCount )
271 	{
272 	docLayoutPushBottomDownShifted( lpBelow, &(paraNode->biBelowPosition),
273 									bo );
274 	}
275 
276   ready:
277 
278     docLayoutCleanBlockFrame( &bf );
279 
280     return rval;
281     }
282 
283