• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**********************************************************************
2  * File:        pdblock.c  (Formerly pdblk.c)
3  * Description: PDBLK member functions and iterator functions.
4  * Author:					Ray Smith
5  * Created:					Fri Mar 15 09:41:28 GMT 1991
6  *
7  * (C) Copyright 1991, Hewlett-Packard Ltd.
8  ** Licensed under the Apache License, Version 2.0 (the "License");
9  ** you may not use this file except in compliance with the License.
10  ** You may obtain a copy of the License at
11  ** http://www.apache.org/licenses/LICENSE-2.0
12  ** Unless required by applicable law or agreed to in writing, software
13  ** distributed under the License is distributed on an "AS IS" BASIS,
14  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  ** See the License for the specific language governing permissions and
16  ** limitations under the License.
17  *
18  **********************************************************************/
19 
20 #include "mfcpch.h"
21 #include          <stdlib.h>
22 #include          "blckerr.h"
23 #include          "pdblock.h"
24 #include          "svshowim.h"
25 
26 #include          "hpddef.h"     //must be last (handpd.dll)
27 
28 #define BLOCK_LABEL_HEIGHT  150  //char height of block id
29 
CLISTIZE(PDBLK)30 CLISTIZE (PDBLK)
31 /**********************************************************************
32  * PDBLK::PDBLK
33  *
34  * Constructor for a simple rectangular block.
35  **********************************************************************/
36 PDBLK::PDBLK (                   //rectangular block
37 inT16 xmin,                      //bottom left
38 inT16 ymin, inT16 xmax,          //top right
39 inT16 ymax):    box (ICOORD (xmin, ymin), ICOORD (xmax, ymax)) {
40                                  //boundaries
41   ICOORDELT_IT left_it = &leftside;
42   ICOORDELT_IT right_it = &rightside;
43 
44   hand_poly = NULL;
45   left_it.set_to_list (&leftside);
46   right_it.set_to_list (&rightside);
47                                  //make default box
48   left_it.add_to_end (new ICOORDELT (xmin, ymin));
49   left_it.add_to_end (new ICOORDELT (xmin, ymax));
50   right_it.add_to_end (new ICOORDELT (xmax, ymin));
51   right_it.add_to_end (new ICOORDELT (xmax, ymax));
52   index_ = 0;
53 }
54 
55 
56 /**********************************************************************
57  * PDBLK::set_sides
58  *
59  * Sets left and right vertex lists
60  **********************************************************************/
61 
set_sides(ICOORDELT_LIST * left,ICOORDELT_LIST * right)62 void PDBLK::set_sides(                       //set vertex lists
63                       ICOORDELT_LIST *left,  //left vertices
64                       ICOORDELT_LIST *right  //right vertices
65                      ) {
66                                  //boundaries
67   ICOORDELT_IT left_it = &leftside;
68   ICOORDELT_IT right_it = &rightside;
69 
70   leftside.clear ();
71   left_it.move_to_first ();
72   left_it.add_list_before (left);
73   rightside.clear ();
74   right_it.move_to_first ();
75   right_it.add_list_before (right);
76 }
77 
78 
79 /**********************************************************************
80  * PDBLK::contains
81  *
82  * Return TRUE if the given point is within the block.
83  **********************************************************************/
84 
contains(ICOORD pt)85 BOOL8 PDBLK::contains(           //test containment
86                       ICOORD pt  //point to test
87                      ) {
88   BLOCK_RECT_IT it = this;       //rectangle iterator
89   ICOORD bleft, tright;          //corners of rectangle
90 
91   for (it.start_block (); !it.cycled_rects (); it.forward ()) {
92                                  //get rectangle
93     it.bounding_box (bleft, tright);
94                                  //inside rect
95     if (pt.x () >= bleft.x () && pt.x () <= tright.x ()
96       && pt.y () >= bleft.y () && pt.y () <= tright.y ())
97       return TRUE;               //is inside
98   }
99   return FALSE;                  //not inside
100 }
101 
102 
103 /**********************************************************************
104  * PDBLK::move
105  *
106  * Reposition block
107  **********************************************************************/
108 
move(const ICOORD vec)109 void PDBLK::move(                  // reposition block
110                  const ICOORD vec  // by vector
111                 ) {
112   ICOORDELT_IT it(&leftside);
113 
114   for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
115     *(it.data ()) += vec;
116 
117   it.set_to_list (&rightside);
118 
119   for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ())
120     *(it.data ()) += vec;
121 
122   box.move (vec);
123 }
124 
125 
126 /**********************************************************************
127  * PDBLK::plot
128  *
129  * Plot the outline of a block in the given colour.
130  **********************************************************************/
131 
132 #ifndef GRAPHICS_DISABLED
plot(ScrollView * window,inT32 serial,ScrollView::Color colour)133 void PDBLK::plot(                //draw outline
134                  ScrollView* window,  //window to draw in
135                  inT32 serial,   //serial number
136                  ScrollView::Color colour   //colour to draw in
137                 ) {
138   ICOORD startpt;                //start of outline
139   ICOORD endpt;                  //end of outline
140   ICOORD prevpt;                 //previous point
141   ICOORDELT_IT it = &leftside;   //iterator
142 
143                                  //set the colour
144   window->Pen(colour);
145   window->TextAttributes("Times", BLOCK_LABEL_HEIGHT, false, false, false);
146 
147   if (hand_poly != NULL) {
148     hand_poly->plot(window, serial);
149   } else if (!leftside.empty ()) {
150     startpt = *(it.data ());     //bottom left corner
151     //              tprintf("Block %d bottom left is (%d,%d)\n",
152     //                      serial,startpt.x(),startpt.y());
153     char temp_buff[34];
154     #ifdef __UNIX__
155     sprintf(temp_buff, INT32FORMAT, serial);
156     #else
157     ultoa (serial, temp_buff, 10);
158     #endif
159     window->Text(startpt.x (), startpt.y (), temp_buff);
160 
161     window->SetCursor(startpt.x (), startpt.y ());
162     do {
163       prevpt = *(it.data ());    //previous point
164       it.forward ();             //move to next point
165                                  //draw round corner
166     window->DrawTo(prevpt.x (), it.data ()->y ());
167     window->DrawTo(it.data ()->x (), it.data ()->y ());
168     }
169     while (!it.at_last ());      //until end of list
170     endpt = *(it.data ());       //end point
171 
172                                  //other side of boundary
173     window->SetCursor(startpt.x (), startpt.y ());
174     it.set_to_list (&rightside);
175     prevpt = startpt;
176     for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) {
177                                  //draw round corner
178     window->DrawTo(prevpt.x (), it.data ()->y ());
179     window->DrawTo(it.data ()->x (), it.data ()->y ());
180       prevpt = *(it.data ());    //previous point
181     }
182                                  //close boundary
183     window->DrawTo(endpt.x(), endpt.y());
184   }
185 }
186 #endif
187 
188 
189 /**********************************************************************
190  * PDBLK::show
191  *
192  * Show the image corresponding to a block as its set of rectangles.
193  **********************************************************************/
194 
195 #ifndef GRAPHICS_DISABLED
show(IMAGE * image,ScrollView * window)196 void PDBLK::show(               //show image block
197                  IMAGE *image,  //image to show
198                  ScrollView* window  //window to show in
199                 ) {
200   BLOCK_RECT_IT it = this;       //rectangle iterator
201   ICOORD bleft, tright;          //corners of rectangle
202 
203   for (it.start_block (); !it.cycled_rects (); it.forward ()) {
204                                  //get rectangle
205     it.bounding_box (bleft, tright);
206     //              tprintf("Drawing a block with a bottom left of (%d,%d)\n",
207     //                      bleft.x(),bleft.y());
208                                  //show it
209     sv_show_sub_image (image, bleft.x (), bleft.y (), tright.x () - bleft.x (), tright.y () - bleft.y (), window, bleft.x (), bleft.y ());
210   }
211 }
212 #endif
213 
214 
215 /**********************************************************************
216  * PDBLK::operator=
217  *
218  * Assignment - duplicate the block structure, but with an EMPTY row list.
219  **********************************************************************/
220 
operator =(const PDBLK & source)221 PDBLK & PDBLK::operator= (       //assignment
222 const PDBLK & source             //from this
223 ) {
224   //      this->ELIST_LINK::operator=(source);
225   if (!leftside.empty ())
226     leftside.clear ();
227   if (!rightside.empty ())
228     rightside.clear ();
229   leftside.deep_copy(&source.leftside, &ICOORDELT::deep_copy);
230   rightside.deep_copy(&source.rightside, &ICOORDELT::deep_copy);
231   box = source.box;
232   return *this;
233 }
234 
235 
236 /**********************************************************************
237  * BLOCK_RECT_IT::BLOCK_RECT_IT
238  *
239  * Construct a block rectangle iterator.
240  **********************************************************************/
241 
BLOCK_RECT_IT(PDBLK * blkptr)242 BLOCK_RECT_IT::BLOCK_RECT_IT (
243 //iterate rectangles
244 PDBLK * blkptr                   //from block
245 ):left_it (&blkptr->leftside), right_it (&blkptr->rightside) {
246   block = blkptr;                //remember block
247                                  //non empty list
248   if (!blkptr->leftside.empty ()) {
249     start_block();  //ready for iteration
250   }
251 }
252 
253 
254 /**********************************************************************
255  * BLOCK_RECT_IT::set_to_block
256  *
257  * Start a new block.
258  **********************************************************************/
259 
set_to_block(PDBLK * blkptr)260 void BLOCK_RECT_IT::set_to_block(                  //start (new) block
261                                  PDBLK *blkptr) {  //block to start
262   block = blkptr;                //remember block
263                                  //set iterators
264   left_it.set_to_list (&blkptr->leftside);
265   right_it.set_to_list (&blkptr->rightside);
266   if (!blkptr->leftside.empty ())
267     start_block();  //ready for iteration
268 }
269 
270 
271 /**********************************************************************
272  * BLOCK_RECT_IT::start_block
273  *
274  * Restart a block.
275  **********************************************************************/
276 
start_block()277 void BLOCK_RECT_IT::start_block() {  //start (new) block
278   left_it.move_to_first ();
279   right_it.move_to_first ();
280   left_it.mark_cycle_pt ();
281   right_it.mark_cycle_pt ();
282   ymin = left_it.data ()->y ();  //bottom of first box
283   ymax = left_it.data_relative (1)->y ();
284   if (right_it.data_relative (1)->y () < ymax)
285                                  //smallest step
286     ymax = right_it.data_relative (1)->y ();
287 }
288 
289 
290 /**********************************************************************
291  * BLOCK_RECT_IT::forward
292  *
293  * Move to the next rectangle in the block.
294  **********************************************************************/
295 
forward()296 void BLOCK_RECT_IT::forward() {  //next rectangle
297   if (!left_it.empty ()) {       //non-empty list
298     if (left_it.data_relative (1)->y () == ymax)
299       left_it.forward ();        //move to meet top
300     if (right_it.data_relative (1)->y () == ymax)
301       right_it.forward ();
302                                  //last is special
303     if (left_it.at_last () || right_it.at_last ()) {
304       left_it.move_to_first ();  //restart
305       right_it.move_to_first ();
306                                  //now at bottom
307       ymin = left_it.data ()->y ();
308     }
309     else {
310       ymin = ymax;               //new bottom
311     }
312                                  //next point
313     ymax = left_it.data_relative (1)->y ();
314     if (right_it.data_relative (1)->y () < ymax)
315                                  //least step forward
316       ymax = right_it.data_relative (1)->y ();
317   }
318 }
319 
320 
321 /**********************************************************************
322  * BLOCK_LINE_IT::get_line
323  *
324  * Get the the start and width of a line in the block.
325  **********************************************************************/
326 
get_line(inT16 y,inT16 & xext)327 inT16 BLOCK_LINE_IT::get_line(             //get a line
328                               inT16 y,     //line to get
329                               inT16 &xext  //output extent
330                              ) {
331   ICOORD bleft;                  //bounding box
332   ICOORD tright;                 //of block & rect
333 
334                                  //get block box
335   block->bounding_box (bleft, tright);
336   if (y < bleft.y () || y >= tright.y ()) {
337     //              block->print(stderr,FALSE);
338     BADBLOCKLINE.error ("BLOCK_LINE_IT::get_line", ABORT, "Y=%d", y);
339   }
340 
341                                  //get rectangle box
342   rect_it.bounding_box (bleft, tright);
343                                  //inside rectangle
344   if (y >= bleft.y () && y < tright.y ()) {
345                                  //width of line
346     xext = tright.x () - bleft.x ();
347     return bleft.x ();           //start of line
348   }
349   for (rect_it.start_block (); !rect_it.cycled_rects (); rect_it.forward ()) {
350                                  //get rectangle box
351     rect_it.bounding_box (bleft, tright);
352                                  //inside rectangle
353     if (y >= bleft.y () && y < tright.y ()) {
354                                  //width of line
355       xext = tright.x () - bleft.x ();
356       return bleft.x ();         //start of line
357     }
358   }
359   LOSTBLOCKLINE.error ("BLOCK_LINE_IT::get_line", ABORT, "Y=%d", y);
360   return 0;                      //dummy to stop warning
361 }
362