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