Coverage Report

Created: 2025-12-03 07:00

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/mupdf/source/fitz/stext-iterator.c
Line
Count
Source
1
// Copyright (C) 2004-2025 Artifex Software, Inc.
2
//
3
// This file is part of MuPDF.
4
//
5
// MuPDF is free software: you can redistribute it and/or modify it under the
6
// terms of the GNU Affero General Public License as published by the Free
7
// Software Foundation, either version 3 of the License, or (at your option)
8
// any later version.
9
//
10
// MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY
11
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
12
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
13
// details.
14
//
15
// You should have received a copy of the GNU Affero General Public License
16
// along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html>
17
//
18
// Alternative licensing terms are available from the licensor.
19
// For commercial licensing, see <https://www.artifex.com/> or contact
20
// Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco,
21
// CA 94129, USA, for further information.
22
23
#include "mupdf/fitz.h"
24
25
fz_stext_page_block_iterator fz_stext_page_block_iterator_begin(fz_stext_page *page)
26
0
{
27
0
  fz_stext_page_block_iterator pos;
28
29
0
  pos.page = page;
30
0
  pos.parent = NULL;
31
0
  pos.block = page ? page->first_block : NULL;
32
33
0
  return pos;
34
0
}
35
36
/* Iterates along, stopping at every block. Stops at the end of the run. */
37
fz_stext_page_block_iterator fz_stext_page_block_iterator_next(fz_stext_page_block_iterator pos)
38
0
{
39
  /* If page == NULL, then this iterator can never go anywhere */
40
0
  if (pos.page == NULL)
41
0
    return pos;
42
43
  /* If we've hit EOF, then nowhere else to go. */
44
0
  if (pos.block == NULL)
45
0
    return pos;
46
47
0
  pos.block = pos.block->next;
48
0
  return pos;
49
0
}
50
51
fz_stext_page_block_iterator fz_stext_page_block_iterator_down(fz_stext_page_block_iterator pos)
52
0
{
53
  /* Can't throw here, so trying to move down on illegal nodes
54
   * will just do nothing. */
55
0
  if (pos.block == NULL)
56
0
    return pos;
57
0
  if (pos.block->type != FZ_STEXT_BLOCK_STRUCT)
58
0
    return pos;
59
60
0
  pos.parent = pos.block->u.s.down;
61
0
  pos.block = pos.block->u.s.down->first_block;
62
63
0
  return pos;
64
0
}
65
66
fz_stext_page_block_iterator fz_stext_page_block_iterator_up(fz_stext_page_block_iterator pos)
67
0
{
68
0
  if (pos.parent == NULL)
69
0
    return pos;
70
71
  /* pos.parent->up is the struct block we are currently traversing the
72
   * children of. So it's where we want to do 'next' from. */
73
0
  pos.block = pos.parent->up;
74
  /* pos.parent->parent is the struct that owns the new pos.block */
75
0
  pos.parent = pos.parent->parent;
76
77
0
  return pos;
78
0
}
79
80
/* Iterates along, and automatically (silently) goes down at structure
81
 * nodes and up at the end of runs. */
82
fz_stext_page_block_iterator fz_stext_page_block_iterator_next_dfs(fz_stext_page_block_iterator pos)
83
0
{
84
0
  while (1)
85
0
  {
86
0
    pos = fz_stext_page_block_iterator_next(pos);
87
88
0
    if (pos.block)
89
0
    {
90
0
      if (pos.block->type != FZ_STEXT_BLOCK_STRUCT)
91
0
        return pos;
92
93
      /* Move down. And loop. */
94
0
      pos.parent = pos.block->u.s.down;
95
0
      pos.block = pos.block->u.s.down->first_block;
96
0
      continue;
97
0
    }
98
99
    /* We've hit the end of the row. Move up. */
100
    /* If no parent, we've really hit the EOD. */
101
0
    if (pos.parent == NULL)
102
0
      return pos; /* EOF */
103
    /* pos.parent->up is the struct block we are currently traversing the
104
     * children of. So it's where we want to do 'next' from. */
105
0
    pos.block = pos.parent->up;
106
    /* pos.parent->parent is the struct that owns the new pos.block */
107
0
    pos.parent = pos.parent->parent;
108
0
  }
109
0
}
110
111
int fz_stext_page_block_iterator_eod(fz_stext_page_block_iterator pos)
112
0
{
113
0
  return (pos.block == NULL);
114
0
}
115
116
int fz_stext_page_block_iterator_eod_dfs(fz_stext_page_block_iterator pos)
117
0
{
118
0
  while (1)
119
0
  {
120
0
    if (pos.block)
121
0
      return 0;
122
0
    if (pos.parent == NULL)
123
0
      return 1;
124
0
    pos.block = pos.parent->up;
125
0
    pos.parent = pos.parent->parent;
126
0
  }
127
0
}