blob: 0e48394c2d1a1c1030612cc4bb106fba1ae3d5b4 [file] [log] [blame]
/**********************************************************************
* File: blread.cpp (Formerly pdread.c)
* Description: Friend function of BLOCK to read the uscan pd file.
* Author: Ray Smith
* Created: Mon Mar 18 14:39:00 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>
#ifdef __UNIX__
#include <assert.h>
#endif
#include "scanutils.h"
#include "fileerr.h"
#include "imgtiff.h"
#include "pdclass.h"
#include "rwpoly.h"
#include "blread.h"
#define PD_EXT ".pd"
#define VEC_EXT ".vec" //accupage file
#define HPD_EXT ".bl" //hand pd file
//unlv zone file
#define UNLV_EXT ".uzn"
#define BLOCK_EXPANSION 8 //boundary expansion
#define EXTERN
EXTERN BOOL_EVAR (ignore_weird_blocks, TRUE, "Don't read weird blocks");
static TBOX convert_vec_block( //make non-rect block
VEC_ENTRY *entries, //vectors
uinT16 entry_count, //no of entries
inT32 ysize, //image size
ICOORDELT_IT *left_it, //block sides
ICOORDELT_IT *right_it);
/**********************************************************************
* BLOCK::read_pd_file
*
* Read a whole pd file to make a list of blocks, or return false.
**********************************************************************/
BOOL8 read_pd_file( //print list of sides
STRING name, //basename of file
inT32 xsize, //image size
inT32 ysize, //image size
BLOCK_LIST *blocks //output list
) {
FILE *pdfp; //file pointer
BLOCK *block; //current block
inT32 block_count; //no of blocks
inT32 junk_count; //no of junks to read
inT32 junks[4]; //junk elements
inT32 vertex_count; //boundary vertices
inT32 xcoord; //current coords
inT32 ycoord;
inT32 prevx; //previous coords
inT32 prevy;
BLOCK_IT block_it = blocks; //block iterator
ICOORDELT_LIST dummy; //for constructor
ICOORDELT_IT left_it = &dummy; //iterator
ICOORDELT_IT right_it = &dummy;//iterator
if (read_hpd_file (name, xsize, ysize, blocks))
return TRUE; //succeeded
if (read_vec_file (name, xsize, ysize, blocks))
return TRUE; //succeeded
if (read_unlv_file (name, xsize, ysize, blocks))
return TRUE; //succeeded
name += PD_EXT; //add extension
if ((pdfp = fopen (name.string (), "r")) == NULL) {
//make rect block
return FALSE; //didn't read one
}
else {
if (fread (&block_count, sizeof (block_count), 1, pdfp) != 1)
READFAILED.error ("read_pd_file", EXIT, "Block count");
tprintf ("%d blocks in .pd file.\n", block_count);
while (block_count > 0) {
if (fread (&junk_count, sizeof (junk_count), 1, pdfp) != 1)
READFAILED.error ("read_pd_file", EXIT, "Junk count");
if (fread (&vertex_count, sizeof (vertex_count), 1, pdfp) != 1)
READFAILED.error ("read_pd_file", EXIT, "Vertex count");
block = new BLOCK; //make a block
//on end of list
block_it.add_to_end (block);
left_it.set_to_list (&block->leftside);
right_it.set_to_list (&block->rightside);
//read a pair
get_pd_vertex (pdfp, xsize, ysize, &block->box, xcoord, ycoord);
vertex_count -= 2; //count read ones
prevx = xcoord;
do {
if (xcoord == prevx) {
if (!right_it.empty ()) {
if (right_it.data ()->x () <= xcoord + BLOCK_EXPANSION)
right_it.data ()->set_y (right_it.data ()->y () +
BLOCK_EXPANSION);
else
right_it.data ()->set_y (right_it.data ()->y () -
BLOCK_EXPANSION);
}
right_it.
add_before_then_move (new
ICOORDELT (xcoord + BLOCK_EXPANSION,
ycoord));
}
prevx = xcoord; //remember previous
prevy = ycoord;
get_pd_vertex (pdfp, xsize, ysize, &block->box, xcoord, ycoord);
vertex_count -= 2; //count read ones
}
while (ycoord <= prevy);
right_it.data ()->set_y (right_it.data ()->y () - BLOCK_EXPANSION);
//start of left
left_it.add_to_end (new ICOORDELT (prevx - BLOCK_EXPANSION, prevy - BLOCK_EXPANSION));
do {
prevx = xcoord; //remember previous
get_pd_vertex (pdfp, xsize, ysize, &block->box, xcoord, ycoord);
vertex_count -= 2;
if (xcoord != prevx && vertex_count > 0) {
if (xcoord > prevx)
left_it.
add_to_end (new
ICOORDELT (xcoord - BLOCK_EXPANSION,
ycoord + BLOCK_EXPANSION));
else
left_it.
add_to_end (new
ICOORDELT (xcoord - BLOCK_EXPANSION,
ycoord - BLOCK_EXPANSION));
}
else if (vertex_count == 0)
left_it.add_to_end (new ICOORDELT (prevx - BLOCK_EXPANSION,
ycoord + BLOCK_EXPANSION));
}
while (vertex_count > 0); //until all read
while (junk_count > 0) {
if (fread (junks, sizeof (inT32), 4, pdfp) != 4)
READFAILED.error ("read_pd_file", EXIT, "Junk coords");
junk_count--;
}
block_count--; //count read blocks
}
}
fclose(pdfp);
return TRUE; //read one
}
/**********************************************************************
* get_pd_vertex
*
* Read a pair of coords, invert the y and clip to image limits.
* Also update the bounding box.
*
* Read a whole pd file to make a list of blocks, or use the whole page.
**********************************************************************/
void get_pd_vertex( //get new vertex
FILE *pdfp, //file to read
inT32 xsize, //image size
inT32 ysize, //image size
TBOX *box, //bounding box
inT32 &xcoord, //output coords
inT32 &ycoord) {
TBOX new_coord; //expansion box
//get new coords
if (fread (&xcoord, sizeof (xcoord), 1, pdfp) != 1)
READFAILED.error ("read_pd_file", EXIT, "Xcoord");
if (fread (&ycoord, sizeof (ycoord), 1, pdfp) != 1)
READFAILED.error ("read_pd_file", EXIT, "Xcoord");
ycoord = ysize - ycoord; //invert y
if (xcoord < BLOCK_EXPANSION)
xcoord = BLOCK_EXPANSION; //clip to limits
if (xcoord > xsize - BLOCK_EXPANSION)
xcoord = xsize - BLOCK_EXPANSION;
if (ycoord < BLOCK_EXPANSION)
ycoord = BLOCK_EXPANSION;
if (ycoord > ysize - BLOCK_EXPANSION)
ycoord = ysize - BLOCK_EXPANSION;
new_coord =
TBOX (ICOORD (xcoord - BLOCK_EXPANSION, ycoord - BLOCK_EXPANSION),
ICOORD (xcoord + BLOCK_EXPANSION, ycoord + BLOCK_EXPANSION));
(*box) += new_coord;
}
/**********************************************************************
* BLOCK::read_hpd_file
*
* Read a whole hpd file to make a list of blocks.
* Return FALSE if the .vec fiel cannot be found
**********************************************************************/
BOOL8 read_hpd_file( //print list of sides
STRING name, //basename of file
inT32 xsize, //image size
inT32 ysize, //image size
BLOCK_LIST *blocks //output list
) {
FILE *pdfp; //file pointer
PAGE_BLOCK_LIST *page_blocks;
inT32 block_no; //no of blocks
BLOCK_IT block_it = blocks; //block iterator
name += HPD_EXT; //add extension
if ((pdfp = fopen (name.string (), "r")) == NULL) {
return FALSE; //can't find it
}
fclose(pdfp);
page_blocks = read_poly_blocks (name.string ());
block_no = 0;
scan_hpd_blocks (name.string (), page_blocks, block_no, &block_it);
tprintf ("Text region count=%d\n", block_no);
return TRUE; //read one
}
/**********************************************************************
* BLOCK::scan_hpd_blocks
*
* Read a whole hpd file to make a list of blocks.
* Return FALSE if the .vec fiel cannot be found
**********************************************************************/
void scan_hpd_blocks( //print list of sides
const char *name, //block label
PAGE_BLOCK_LIST *page_blocks, //head of full pag
inT32 &block_no, //no of blocks
BLOCK_IT *block_it //block iterator
) {
BLOCK *block; //current block
//page blocks
PAGE_BLOCK_IT pb_it = page_blocks;
PAGE_BLOCK *current_block;
TEXT_REGION_IT tr_it;
TEXT_BLOCK *tb;
TEXT_REGION *tr;
TBOX *block_box; //from text region
for (pb_it.mark_cycle_pt (); !pb_it.cycled_list (); pb_it.forward ()) {
current_block = pb_it.data ();
if (current_block->type () == PB_TEXT) {
tb = (TEXT_BLOCK *) current_block;
if (!tb->regions ()->empty ()) {
tr_it.set_to_list (tb->regions ());
for (tr_it.mark_cycle_pt ();
!tr_it.cycled_list (); tr_it.forward ()) {
block_no++;
tr = tr_it.data ();
block_box = tr->bounding_box ();
block = new BLOCK (name, TRUE, 0, 0,
block_box->left (), block_box->bottom (),
block_box->right (), block_box->top ());
block->hand_block = tr;
block->hand_poly = tr;
block_it->add_after_then_move (block);
}
}
}
else if (current_block->type () == PB_WEIRD
&& !ignore_weird_blocks
&& ((WEIRD_BLOCK *) current_block)->id_no () > 0) {
block_no++;
block_box = current_block->bounding_box ();
block = new BLOCK (name, TRUE, 0, 0,
block_box->left (), block_box->bottom (),
block_box->right (), block_box->top ());
block->hand_block = NULL;
block->hand_poly = current_block;
block_it->add_after_then_move (block);
}
if (!current_block->child ()->empty ())
scan_hpd_blocks (name, current_block->child (), block_no, block_it);
}
}
/**********************************************************************
* BLOCK::read_vec_file
*
* Read a whole vec file to make a list of blocks.
* Return FALSE if the .vec fiel cannot be found
**********************************************************************/
BOOL8 read_vec_file( //print list of sides
STRING name, //basename of file
inT32 xsize, //image size
inT32 ysize, //image size
BLOCK_LIST *blocks //output list
) {
FILE *pdfp; //file pointer
BLOCK *block; //current block
inT32 block_no; //no of blocks
inT32 block_index; //current blocks
inT32 vector_count; //total vectors
VEC_HEADER header; //file header
BLOCK_HEADER *vec_blocks; //blocks from file
VEC_ENTRY *vec_entries; //vectors from file
BLOCK_IT block_it = blocks; //block iterator
ICOORDELT_IT left_it; //iterators
ICOORDELT_IT right_it;
name += VEC_EXT; //add extension
if ((pdfp = fopen (name.string (), "r")) == NULL) {
return FALSE; //can't find it
}
if (fread (&header, sizeof (header), 1, pdfp) != 1)
READFAILED.error ("read_vec_file", EXIT, "Header");
//from intel
header.filesize = reverse32 (header.filesize);
header.bytesize = reverse16 (header.bytesize);
header.arraysize = reverse16 (header.arraysize);
header.width = reverse16 (header.width);
header.height = reverse16 (header.height);
header.res = reverse16 (header.res);
header.bpp = reverse16 (header.bpp);
tprintf ("%d blocks in %s file:", header.arraysize, VEC_EXT);
vector_count = header.filesize - header.arraysize * sizeof (BLOCK_HEADER);
vector_count /= sizeof (VEC_ENTRY);
vec_blocks =
(BLOCK_HEADER *) alloc_mem (header.arraysize * sizeof (BLOCK_HEADER));
vec_entries = (VEC_ENTRY *) alloc_mem (vector_count * sizeof (VEC_ENTRY));
xsize = header.width; //real image size
ysize = header.height;
if (fread (vec_blocks, sizeof (BLOCK_HEADER), header.arraysize, pdfp)
!= static_cast<size_t>(header.arraysize))
READFAILED.error ("read_vec_file", EXIT, "Blocks");
if (fread (vec_entries, sizeof (VEC_ENTRY), vector_count, pdfp)
!= static_cast<size_t>(vector_count))
READFAILED.error ("read_vec_file", EXIT, "Vectors");
for (block_index = 0; block_index < header.arraysize; block_index++) {
vec_blocks[block_index].offset =
reverse16 (vec_blocks[block_index].offset);
vec_blocks[block_index].order =
reverse16 (vec_blocks[block_index].order);
vec_blocks[block_index].entries =
reverse16 (vec_blocks[block_index].entries);
vec_blocks[block_index].charsize =
reverse16 (vec_blocks[block_index].charsize);
}
for (block_index = 0; block_index < vector_count; block_index++) {
vec_entries[block_index].start =
ICOORD (reverse16 (vec_entries[block_index].start.x ()),
reverse16 (vec_entries[block_index].start.y ()));
vec_entries[block_index].end =
ICOORD (reverse16 (vec_entries[block_index].end.x ()),
reverse16 (vec_entries[block_index].end.y ()));
}
for (block_no = 1; block_no <= header.arraysize; block_no++) {
for (block_index = 0; block_index < header.arraysize; block_index++) {
if (vec_blocks[block_index].order == block_no
&& vec_blocks[block_index].valid) {
block = new BLOCK;
left_it.set_to_list (&block->leftside);
right_it.set_to_list (&block->rightside);
block->box =
convert_vec_block (&vec_entries
[vec_blocks[block_index].offset],
vec_blocks[block_index].entries, ysize,
&left_it, &right_it);
block->set_xheight (vec_blocks[block_index].charsize);
//on end of list
block_it.add_to_end (block);
// tprintf("Block at (%d,%d)->(%d,%d) has index %d and order %d\n",
// block->box.left(),
// block->box.bottom(),
// block->box.right(),
// block->box.top(),
// block_index,vec_blocks[block_index].order);
}
}
}
free_mem(vec_blocks);
free_mem(vec_entries);
tprintf ("%d valid\n", block_it.length ());
fclose(pdfp);
return TRUE; //read one
}
/**********************************************************************
* BLOCK::convert_vec_block
*
* Read a whole vec file to make a list of blocks.
* Return FALSE if the .vec fiel cannot be found
**********************************************************************/
static TBOX convert_vec_block( //make non-rect block
VEC_ENTRY *entries, //vectors
uinT16 entry_count, //no of entries
inT32 ysize, //image size
ICOORDELT_IT *left_it, //block sides
ICOORDELT_IT *right_it) {
TBOX block_box; //bounding box
TBOX vec_box; //box of vec
ICOORD box_point; //expanded coord
ICOORD shift_vec; //for box expansion
ICOORD prev_pt; //previous coord
ICOORD end_pt; //end of vector
inT32 vertex_index; //boundary vertices
for (vertex_index = 0; vertex_index < entry_count; vertex_index++) {
entries[vertex_index].start = ICOORD (entries[vertex_index].start.x (),
ysize - 1 -
entries[vertex_index].start.y ());
entries[vertex_index].end =
ICOORD (entries[vertex_index].end.x (),
ysize - 1 - entries[vertex_index].end.y ());
vec_box = TBOX (entries[vertex_index].start, entries[vertex_index].end);
block_box += vec_box; //find total bounds
}
for (vertex_index = 0; vertex_index < entry_count
&& (entries[vertex_index].start.y () != block_box.bottom ()
|| entries[vertex_index].end.y () != block_box.bottom ());
vertex_index++);
ASSERT_HOST (vertex_index < entry_count);
prev_pt = entries[vertex_index].start;
end_pt = entries[vertex_index].end;
do {
for (vertex_index = 0; vertex_index < entry_count
&& entries[vertex_index].start != end_pt; vertex_index++);
//found start of vertical
ASSERT_HOST (vertex_index < entry_count);
box_point = entries[vertex_index].start;
if (box_point.x () <= prev_pt.x ())
shift_vec = ICOORD (-BLOCK_EXPANSION, -BLOCK_EXPANSION);
else
shift_vec = ICOORD (-BLOCK_EXPANSION, BLOCK_EXPANSION);
left_it->add_to_end (new ICOORDELT (box_point + shift_vec));
prev_pt = box_point;
for (vertex_index = 0; vertex_index < entry_count
&& entries[vertex_index].start != end_pt; vertex_index++);
//found horizontal
ASSERT_HOST (vertex_index < entry_count);
end_pt = entries[vertex_index].end;
}
while (end_pt.y () < block_box.top ());
shift_vec = ICOORD (-BLOCK_EXPANSION, BLOCK_EXPANSION);
left_it->add_to_end (new ICOORDELT (end_pt + shift_vec));
for (vertex_index = 0; vertex_index < entry_count
&& (entries[vertex_index].start.y () != block_box.top ()
|| entries[vertex_index].end.y () != block_box.top ());
vertex_index++);
ASSERT_HOST (vertex_index < entry_count);
prev_pt = entries[vertex_index].start;
end_pt = entries[vertex_index].end;
do {
for (vertex_index = 0; vertex_index < entry_count
&& entries[vertex_index].start != end_pt; vertex_index++);
//found start of vertical
ASSERT_HOST (vertex_index < entry_count);
box_point = entries[vertex_index].start;
if (box_point.x () < prev_pt.x ())
shift_vec = ICOORD (BLOCK_EXPANSION, -BLOCK_EXPANSION);
else
shift_vec = ICOORD (BLOCK_EXPANSION, BLOCK_EXPANSION);
right_it->add_before_then_move (new ICOORDELT (box_point + shift_vec));
prev_pt = box_point;
for (vertex_index = 0; vertex_index < entry_count
&& entries[vertex_index].start != end_pt; vertex_index++);
//found horizontal
ASSERT_HOST (vertex_index < entry_count);
end_pt = entries[vertex_index].end;
}
while (end_pt.y () > block_box.bottom ());
shift_vec = ICOORD (BLOCK_EXPANSION, -BLOCK_EXPANSION);
right_it->add_before_then_move (new ICOORDELT (end_pt + shift_vec));
shift_vec = ICOORD (BLOCK_EXPANSION, BLOCK_EXPANSION);
box_point = block_box.botleft () - shift_vec;
end_pt = block_box.topright () + shift_vec;
return TBOX (box_point, end_pt);
}
/**********************************************************************
* read_unlv_file
*
* Read a whole unlv zone file to make a list of blocks.
**********************************************************************/
BOOL8 read_unlv_file( //print list of sides
STRING name, //basename of file
inT32 xsize, //image size
inT32 ysize, //image size
BLOCK_LIST *blocks //output list
) {
FILE *pdfp; //file pointer
BLOCK *block; //current block
int x; //current top-down coords
int y;
int width; //of current block
int height;
BLOCK_IT block_it = blocks; //block iterator
name += UNLV_EXT; //add extension
if ((pdfp = fopen (name.string (), "r")) == NULL) {
return FALSE; //didn't read one
}
else {
while (fscanf (pdfp, "%d %d %d %d %*s", &x, &y, &width, &height) >= 4) {
//make rect block
block = new BLOCK (name.string (), TRUE, 0, 0,
(inT16) x, (inT16) (ysize - y - height),
(inT16) (x + width), (inT16) (ysize - y));
//on end of list
block_it.add_to_end (block);
}
fclose(pdfp);
}
return true;
}