| /********************************************************************** |
| * File: pdblock.c (Formerly pdblk.c) |
| * Description: PDBLK member functions and iterator functions. |
| * Author: Ray Smith |
| * Created: Fri Mar 15 09:41:28 GMT 1991 |
| * |
| * (C) Copyright 1991, Hewlett-Packard Ltd. |
| ** Licensed under the Apache License, Version 2.0 (the "License"); |
| ** you may not use this file except in compliance with the License. |
| ** You may obtain a copy of the License at |
| ** http://www.apache.org/licenses/LICENSE-2.0 |
| ** Unless required by applicable law or agreed to in writing, software |
| ** distributed under the License is distributed on an "AS IS" BASIS, |
| ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| ** See the License for the specific language governing permissions and |
| ** limitations under the License. |
| * |
| **********************************************************************/ |
| |
| #include "mfcpch.h" |
| #include <stdlib.h> |
| #include "blckerr.h" |
| #include "pdblock.h" |
| #include "svshowim.h" |
| |
| #include "hpddef.h" //must be last (handpd.dll) |
| |
| #define BLOCK_LABEL_HEIGHT 150 //char height of block id |
| |
| CLISTIZE (PDBLK) |
| /********************************************************************** |
| * PDBLK::PDBLK |
| * |
| * Constructor for a simple rectangular block. |
| **********************************************************************/ |
| PDBLK::PDBLK ( //rectangular block |
| inT16 xmin, //bottom left |
| inT16 ymin, inT16 xmax, //top right |
| inT16 ymax): box (ICOORD (xmin, ymin), ICOORD (xmax, ymax)) { |
| //boundaries |
| ICOORDELT_IT left_it = &leftside; |
| ICOORDELT_IT right_it = &rightside; |
| |
| hand_block = NULL; |
| hand_poly = NULL; |
| left_it.set_to_list (&leftside); |
| right_it.set_to_list (&rightside); |
| //make default box |
| left_it.add_to_end (new ICOORDELT (xmin, ymin)); |
| left_it.add_to_end (new ICOORDELT (xmin, ymax)); |
| right_it.add_to_end (new ICOORDELT (xmax, ymin)); |
| right_it.add_to_end (new ICOORDELT (xmax, ymax)); |
| } |
| |
| |
| /********************************************************************** |
| * PDBLK::set_sides |
| * |
| * Sets left and right vertex lists |
| **********************************************************************/ |
| |
| void PDBLK::set_sides( //set vertex lists |
| ICOORDELT_LIST *left, //left vertices |
| ICOORDELT_LIST *right //right vertices |
| ) { |
| //boundaries |
| ICOORDELT_IT left_it = &leftside; |
| ICOORDELT_IT right_it = &rightside; |
| |
| leftside.clear (); |
| left_it.move_to_first (); |
| left_it.add_list_before (left); |
| rightside.clear (); |
| right_it.move_to_first (); |
| right_it.add_list_before (right); |
| } |
| |
| |
| /********************************************************************** |
| * PDBLK::contains |
| * |
| * Return TRUE if the given point is within the block. |
| **********************************************************************/ |
| |
| BOOL8 PDBLK::contains( //test containment |
| ICOORD pt //point to test |
| ) { |
| BLOCK_RECT_IT it = this; //rectangle iterator |
| ICOORD bleft, tright; //corners of rectangle |
| |
| for (it.start_block (); !it.cycled_rects (); it.forward ()) { |
| //get rectangle |
| it.bounding_box (bleft, tright); |
| //inside rect |
| if (pt.x () >= bleft.x () && pt.x () <= tright.x () |
| && pt.y () >= bleft.y () && pt.y () <= tright.y ()) |
| return TRUE; //is inside |
| } |
| return FALSE; //not inside |
| } |
| |
| |
| /********************************************************************** |
| * PDBLK::move |
| * |
| * Reposition block |
| **********************************************************************/ |
| |
| void PDBLK::move( // reposition block |
| const ICOORD vec // by vector |
| ) { |
| ICOORDELT_IT it(&leftside); |
| |
| for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) |
| *(it.data ()) += vec; |
| |
| it.set_to_list (&rightside); |
| |
| for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) |
| *(it.data ()) += vec; |
| |
| box.move (vec); |
| } |
| |
| |
| /********************************************************************** |
| * PDBLK::plot |
| * |
| * Plot the outline of a block in the given colour. |
| **********************************************************************/ |
| |
| #ifndef GRAPHICS_DISABLED |
| void PDBLK::plot( //draw outline |
| ScrollView* window, //window to draw in |
| inT32 serial, //serial number |
| ScrollView::Color colour //colour to draw in |
| ) { |
| ICOORD startpt; //start of outline |
| ICOORD endpt; //end of outline |
| ICOORD prevpt; //previous point |
| ICOORDELT_IT it = &leftside; //iterator |
| |
| //set the colour |
| window->Pen(colour); |
| window->TextAttributes("Times", BLOCK_LABEL_HEIGHT, false, false, false); |
| |
| if (!leftside.empty ()) { |
| startpt = *(it.data ()); //bottom left corner |
| // tprintf("Block %d bottom left is (%d,%d)\n", |
| // serial,startpt.x(),startpt.y()); |
| char temp_buff[34]; |
| #ifdef __UNIX__ |
| sprintf(temp_buff, INT32FORMAT, serial); |
| #else |
| ultoa (serial, temp_buff, 10); |
| #endif |
| window->Text(startpt.x (), startpt.y (), temp_buff); |
| |
| window->SetCursor(startpt.x (), startpt.y ()); |
| do { |
| prevpt = *(it.data ()); //previous point |
| it.forward (); //move to next point |
| //draw round corner |
| window->DrawTo(prevpt.x (), it.data ()->y ()); |
| window->DrawTo(it.data ()->x (), it.data ()->y ()); |
| } |
| while (!it.at_last ()); //until end of list |
| endpt = *(it.data ()); //end point |
| |
| //other side of boundary |
| window->SetCursor(startpt.x (), startpt.y ()); |
| it.set_to_list (&rightside); |
| prevpt = startpt; |
| for (it.mark_cycle_pt (); !it.cycled_list (); it.forward ()) { |
| //draw round corner |
| window->DrawTo(prevpt.x (), it.data ()->y ()); |
| window->DrawTo(it.data ()->x (), it.data ()->y ()); |
| prevpt = *(it.data ()); //previous point |
| } |
| //close boundary |
| window->DrawTo(endpt.x(), endpt.y()); |
| if (hand_block != NULL) |
| hand_block->plot (window, colour, serial); |
| } |
| |
| } |
| #endif |
| |
| |
| /********************************************************************** |
| * PDBLK::show |
| * |
| * Show the image corresponding to a block as its set of rectangles. |
| **********************************************************************/ |
| |
| #ifndef GRAPHICS_DISABLED |
| void PDBLK::show( //show image block |
| IMAGE *image, //image to show |
| ScrollView* window //window to show in |
| ) { |
| BLOCK_RECT_IT it = this; //rectangle iterator |
| ICOORD bleft, tright; //corners of rectangle |
| |
| for (it.start_block (); !it.cycled_rects (); it.forward ()) { |
| //get rectangle |
| it.bounding_box (bleft, tright); |
| // tprintf("Drawing a block with a bottom left of (%d,%d)\n", |
| // bleft.x(),bleft.y()); |
| //show it |
| sv_show_sub_image (image, bleft.x (), bleft.y (), tright.x () - bleft.x (), tright.y () - bleft.y (), window, bleft.x (), bleft.y ()); |
| } |
| } |
| #endif |
| |
| |
| /********************************************************************** |
| * PDBLK::operator= |
| * |
| * Assignment - duplicate the block structure, but with an EMPTY row list. |
| **********************************************************************/ |
| |
| PDBLK & PDBLK::operator= ( //assignment |
| const PDBLK & source //from this |
| ) { |
| // this->ELIST_LINK::operator=(source); |
| if (!leftside.empty ()) |
| leftside.clear (); |
| if (!rightside.empty ()) |
| rightside.clear (); |
| leftside.deep_copy (&source.leftside); |
| rightside.deep_copy (&source.rightside); |
| box = source.box; |
| return *this; |
| } |
| |
| |
| /********************************************************************** |
| * BLOCK_RECT_IT::BLOCK_RECT_IT |
| * |
| * Construct a block rectangle iterator. |
| **********************************************************************/ |
| |
| BLOCK_RECT_IT::BLOCK_RECT_IT ( |
| //iterate rectangles |
| PDBLK * blkptr //from block |
| ):left_it (&blkptr->leftside), right_it (&blkptr->rightside) { |
| block = blkptr; //remember block |
| //non empty list |
| if (!blkptr->leftside.empty ()) { |
| start_block(); //ready for iteration |
| } |
| } |
| |
| |
| /********************************************************************** |
| * BLOCK_RECT_IT::set_to_block |
| * |
| * Start a new block. |
| **********************************************************************/ |
| |
| void BLOCK_RECT_IT::set_to_block( //start (new) block |
| PDBLK *blkptr) { //block to start |
| block = blkptr; //remember block |
| //set iterators |
| left_it.set_to_list (&blkptr->leftside); |
| right_it.set_to_list (&blkptr->rightside); |
| if (!blkptr->leftside.empty ()) |
| start_block(); //ready for iteration |
| } |
| |
| |
| /********************************************************************** |
| * BLOCK_RECT_IT::start_block |
| * |
| * Restart a block. |
| **********************************************************************/ |
| |
| void BLOCK_RECT_IT::start_block() { //start (new) block |
| left_it.move_to_first (); |
| right_it.move_to_first (); |
| left_it.mark_cycle_pt (); |
| right_it.mark_cycle_pt (); |
| ymin = left_it.data ()->y (); //bottom of first box |
| ymax = left_it.data_relative (1)->y (); |
| if (right_it.data_relative (1)->y () < ymax) |
| //smallest step |
| ymax = right_it.data_relative (1)->y (); |
| } |
| |
| |
| /********************************************************************** |
| * BLOCK_RECT_IT::forward |
| * |
| * Move to the next rectangle in the block. |
| **********************************************************************/ |
| |
| void BLOCK_RECT_IT::forward() { //next rectangle |
| if (!left_it.empty ()) { //non-empty list |
| if (left_it.data_relative (1)->y () == ymax) |
| left_it.forward (); //move to meet top |
| if (right_it.data_relative (1)->y () == ymax) |
| right_it.forward (); |
| //last is special |
| if (left_it.at_last () || right_it.at_last ()) { |
| left_it.move_to_first (); //restart |
| right_it.move_to_first (); |
| //now at bottom |
| ymin = left_it.data ()->y (); |
| } |
| else { |
| ymin = ymax; //new bottom |
| } |
| //next point |
| ymax = left_it.data_relative (1)->y (); |
| if (right_it.data_relative (1)->y () < ymax) |
| //least step forward |
| ymax = right_it.data_relative (1)->y (); |
| } |
| } |
| |
| |
| /********************************************************************** |
| * BLOCK_LINE_IT::get_line |
| * |
| * Get the the start and width of a line in the block. |
| **********************************************************************/ |
| |
| inT16 BLOCK_LINE_IT::get_line( //get a line |
| inT16 y, //line to get |
| inT16 &xext //output extent |
| ) { |
| ICOORD bleft; //bounding box |
| ICOORD tright; //of block & rect |
| |
| //get block box |
| block->bounding_box (bleft, tright); |
| if (y < bleft.y () || y >= tright.y ()) { |
| // block->print(stderr,FALSE); |
| BADBLOCKLINE.error ("BLOCK_LINE_IT::get_line", ABORT, "Y=%d", y); |
| } |
| |
| //get rectangle box |
| rect_it.bounding_box (bleft, tright); |
| //inside rectangle |
| if (y >= bleft.y () && y < tright.y ()) { |
| //width of line |
| xext = tright.x () - bleft.x (); |
| return bleft.x (); //start of line |
| } |
| for (rect_it.start_block (); !rect_it.cycled_rects (); rect_it.forward ()) { |
| //get rectangle box |
| rect_it.bounding_box (bleft, tright); |
| //inside rectangle |
| if (y >= bleft.y () && y < tright.y ()) { |
| //width of line |
| xext = tright.x () - bleft.x (); |
| return bleft.x (); //start of line |
| } |
| } |
| LOSTBLOCKLINE.error ("BLOCK_LINE_IT::get_line", ABORT, "Y=%d", y); |
| return 0; //dummy to stop warning |
| } |