source: trunk/libdjvu/GRect.cpp @ 17

Last change on this file since 17 was 17, checked in by Eugene Romanenko, 15 years ago

update makefiles, remove absolute paths, update djvulibre to version 3.5.17

File size: 10.3 KB
Line 
1//C-  -*- C++ -*-
2//C- -------------------------------------------------------------------
3//C- DjVuLibre-3.5
4//C- Copyright (c) 2002  Leon Bottou and Yann Le Cun.
5//C- Copyright (c) 2001  AT&T
6//C-
7//C- This software is subject to, and may be distributed under, the
8//C- GNU General Public License, Version 2. The license should have
9//C- accompanied the software or you may obtain a copy of the license
10//C- from the Free Software Foundation at http://www.fsf.org .
11//C-
12//C- This program is distributed in the hope that it will be useful,
13//C- but WITHOUT ANY WARRANTY; without even the implied warranty of
14//C- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15//C- GNU General Public License for more details.
16//C-
17//C- DjVuLibre-3.5 is derived from the DjVu(r) Reference Library
18//C- distributed by Lizardtech Software.  On July 19th 2002, Lizardtech
19//C- Software authorized us to replace the original DjVu(r) Reference
20//C- Library notice by the following text (see doc/lizard2002.djvu):
21//C-
22//C-  ------------------------------------------------------------------
23//C- | DjVu (r) Reference Library (v. 3.5)
24//C- | Copyright (c) 1999-2001 LizardTech, Inc. All Rights Reserved.
25//C- | The DjVu Reference Library is protected by U.S. Pat. No.
26//C- | 6,058,214 and patents pending.
27//C- |
28//C- | This software is subject to, and may be distributed under, the
29//C- | GNU General Public License, Version 2. The license should have
30//C- | accompanied the software or you may obtain a copy of the license
31//C- | from the Free Software Foundation at http://www.fsf.org .
32//C- |
33//C- | The computer code originally released by LizardTech under this
34//C- | license and unmodified by other parties is deemed "the LIZARDTECH
35//C- | ORIGINAL CODE."  Subject to any third party intellectual property
36//C- | claims, LizardTech grants recipient a worldwide, royalty-free,
37//C- | non-exclusive license to make, use, sell, or otherwise dispose of
38//C- | the LIZARDTECH ORIGINAL CODE or of programs derived from the
39//C- | LIZARDTECH ORIGINAL CODE in compliance with the terms of the GNU
40//C- | General Public License.   This grant only confers the right to
41//C- | infringe patent claims underlying the LIZARDTECH ORIGINAL CODE to
42//C- | the extent such infringement is reasonably necessary to enable
43//C- | recipient to make, have made, practice, sell, or otherwise dispose
44//C- | of the LIZARDTECH ORIGINAL CODE (or portions thereof) and not to
45//C- | any greater extent that may be necessary to utilize further
46//C- | modifications or combinations.
47//C- |
48//C- | The LIZARDTECH ORIGINAL CODE is provided "AS IS" WITHOUT WARRANTY
49//C- | OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
50//C- | TO ANY WARRANTY OF NON-INFRINGEMENT, OR ANY IMPLIED WARRANTY OF
51//C- | MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
52//C- +------------------------------------------------------------------
53//
54// $Id: GRect.cpp,v 1.11 2006/02/21 16:10:29 docbill Exp $
55// $Name:  $
56
57#ifdef HAVE_CONFIG_H
58# include "config.h"
59#endif
60#if NEED_GNUG_PRAGMAS
61# pragma implementation
62#endif
63
64// -- Implementation of class GRect and GRectMapper
65// - Author: Leon Bottou, 05/1997
66
67
68#include "GRect.h"
69#include "GException.h"
70
71
72#ifdef HAVE_NAMESPACES
73namespace DJVU {
74# ifdef NOT_DEFINED // Just to fool emacs c++ mode
75}
76#endif
77#endif
78
79// -- Local utilities
80
81static inline int 
82imin(int x, int y)
83{
84  if (x < y) 
85    return x;
86  else
87    return y;
88}
89
90static inline int 
91imax(int x, int y)
92{
93  if (x > y) 
94    return x;
95  else
96    return y;
97}
98
99static inline void
100iswap(int &x, int &y)
101{
102  int tmp = x; x = y; y = tmp;
103}
104
105// -- Class GRect
106
107int 
108operator==(const GRect & r1, const GRect & r2)
109{
110  bool isempty1 = r1.isempty();
111  bool isempty2 = r2.isempty();
112  if (isempty1 || isempty2)
113    if (isempty1 && isempty2)
114      return 1;
115  if ( r1.xmin==r2.xmin && r1.xmax==r2.xmax
116       && r1.ymin==r2.ymin && r1.ymax==r2.ymax )
117    return 1;
118  return 0;
119}
120
121int 
122GRect::inflate(int dx, int dy)
123{
124  xmin -= dx;
125  xmax += dx;
126  ymin -= dy;
127  ymax += dy;
128  if (! isempty()) 
129    return 1;
130  xmin = ymin = xmax = ymax = 0;
131  return 0;
132}
133
134int 
135GRect::translate(int dx, int dy)
136{
137  xmin += dx;
138  xmax += dx;
139  ymin += dy;
140  ymax += dy;
141  if (! isempty()) 
142    return 1;
143  xmin = ymin = xmax = ymax = 0;
144  return 0;
145}
146
147int 
148GRect::intersect(const GRect &rect1, const GRect &rect2)
149{
150  xmin = imax(rect1.xmin, rect2.xmin);
151  xmax = imin(rect1.xmax, rect2.xmax);
152  ymin = imax(rect1.ymin, rect2.ymin);
153  ymax = imin(rect1.ymax, rect2.ymax);
154  if (! isempty()) 
155    return 1;
156  xmin = ymin = xmax = ymax = 0;
157  return 0;
158}
159
160int 
161GRect::recthull(const GRect &rect1, const GRect &rect2)
162{
163  if (rect1.isempty())
164    {
165      xmin = rect2.xmin;
166      xmax = rect2.xmax;
167      ymin = rect2.ymin;
168      ymax = rect2.ymax;
169      return !isempty();
170    }
171  if (rect2.isempty())
172    {
173      xmin = rect1.xmin;
174      xmax = rect1.xmax;
175      ymin = rect1.ymin;
176      ymax = rect1.ymax;
177      return !isempty();
178    }
179  xmin = imin(rect1.xmin, rect2.xmin);
180  xmax = imax(rect1.xmax, rect2.xmax);
181  ymin = imin(rect1.ymin, rect2.ymin);
182  ymax = imax(rect1.ymax, rect2.ymax);
183  return 1;
184}
185
186int
187GRect::contains(const GRect & rect) const
188{
189   GRect tmp_rect;
190   tmp_rect.intersect(*this, rect);
191   return tmp_rect==rect;
192}
193
194void
195GRect::scale(float factor)
196{
197        xmin = (int)(((float)xmin) * factor);
198        ymin = (int)(((float)ymin) * factor);
199        xmax = (int)(((float)xmax) * factor);
200        ymax = (int)(((float)ymax) * factor);
201}
202
203void
204GRect::scale(float xfactor, float yfactor)
205{
206        xmin = (int)(((float)xmin) * xfactor);
207        ymin = (int)(((float)ymin) * yfactor);
208        xmax = (int)(((float)xmax) * xfactor);
209        ymax = (int)(((float)ymax) * yfactor);
210}
211// -- Class GRatio
212
213
214inline
215GRectMapper::GRatio::GRatio()
216  : p(0), q(1)
217{
218}
219
220inline
221GRectMapper::GRatio::GRatio(int p, int q)
222  : p(p), q(q)
223{
224  if (q == 0) 
225    G_THROW( ERR_MSG("GRect.div_zero") );
226  if (p == 0)
227    q = 1;
228  if (q < 0)
229    {
230      p = -p; 
231      q = -q; 
232    }
233  int gcd = 1;
234  int g1 = p; 
235  int g2 = q; 
236  if (g1 > g2)
237    {
238      gcd = g1;
239      g1 = g2;
240      g2 = gcd;
241    }
242  while (g1 > 0)
243    {
244      gcd = g1;
245      g1 = g2 % g1;
246      g2 = gcd;
247    }
248  p /= gcd;
249  q /= gcd;
250}
251
252
253#ifdef HAVE_LONG_LONG_INT
254#define llint_t long long int
255#else
256#define llint_t long int
257#endif
258
259inline int 
260operator*(int n, GRectMapper::GRatio r )
261{ 
262  /* [LB] -- This computation is carried out with integers and
263     rational numbers because it must be exact.  Some lizard changed
264     it to double and this is wrong.  I suspect they did so because
265     they encountered overflow issues.  Let's use long long ints. */
266  llint_t x = (llint_t) n * (llint_t) r.p;
267  if (x >= 0)
268    return   ((r.q/2 + x) / r.q);
269  else
270    return - ((r.q/2 - x) / r.q);
271}
272
273inline int 
274operator/(int n, GRectMapper::GRatio r )
275{ 
276  /* [LB] -- See comment in operator*() above. */
277  llint_t x = (llint_t) n * (llint_t) r.q;
278  if (x >= 0)
279    return   ((r.p/2 + x) / r.p);
280  else
281    return - ((r.p/2 - x) / r.p);
282}
283
284
285// -- Class GRectMapper
286
287#define MIRRORX  1
288#define MIRRORY  2
289#define SWAPXY 4
290
291
292GRectMapper::GRectMapper()
293: rectFrom(0,0,1,1), 
294  rectTo(0,0,1,1),
295  code(0)
296{
297
298}
299
300void
301GRectMapper::clear()
302{
303  rectFrom = GRect(0,0,1,1);
304  rectTo = GRect(0,0,1,1);
305  code = 0;
306}
307
308void 
309GRectMapper::set_input(const GRect &rect)
310{
311  if (rect.isempty())
312    G_THROW( ERR_MSG("GRect.empty_rect1") );
313  rectFrom = rect;
314  if (code & SWAPXY)
315  {
316    iswap(rectFrom.xmin, rectFrom.ymin);
317    iswap(rectFrom.xmax, rectFrom.ymax);
318  }
319  rw = rh = GRatio();
320}
321
322void 
323GRectMapper::set_output(const GRect &rect)
324{
325  if (rect.isempty())
326    G_THROW( ERR_MSG("GRect.empty_rect2") );
327  rectTo = rect;
328  rw = rh = GRatio();
329}
330
331void 
332GRectMapper::rotate(int count)
333{
334  int oldcode = code;
335  switch (count & 0x3)
336    {
337    case 1:
338      code ^= (code & SWAPXY) ? MIRRORY : MIRRORX;
339      code ^= SWAPXY;
340      break;
341    case 2:
342      code ^= (MIRRORX|MIRRORY);
343      break;
344    case 3:
345      code ^= (code & SWAPXY) ? MIRRORX : MIRRORY;
346      code ^= SWAPXY;
347      break;
348    }
349  if ((oldcode ^ code) & SWAPXY)
350    { 
351      iswap(rectFrom.xmin, rectFrom.ymin);
352      iswap(rectFrom.xmax, rectFrom.ymax);
353      rw = rh = GRatio();
354    }
355}
356
357void 
358GRectMapper::mirrorx()
359{
360  code ^= MIRRORX;
361}
362
363void 
364GRectMapper::mirrory()
365{
366  code ^= MIRRORY;
367}
368
369void
370GRectMapper::precalc()
371{
372  if (rectTo.isempty() || rectFrom.isempty())
373    G_THROW( ERR_MSG("GRect.empty_rect3") );
374  rw = GRatio(rectTo.width(), rectFrom.width());
375  rh = GRatio(rectTo.height(), rectFrom.height());
376}
377
378void 
379GRectMapper::map(int &x, int &y)
380{
381  int mx = x;
382  int my = y;
383  // precalc
384  if (! (rw.p && rh.p))
385    precalc();
386  // swap and mirror
387  if (code & SWAPXY)
388    iswap(mx,my);
389  if (code & MIRRORX)
390    mx = rectFrom.xmin + rectFrom.xmax - mx;
391  if (code & MIRRORY)
392    my = rectFrom.ymin + rectFrom.ymax - my;
393  // scale and translate
394  x = rectTo.xmin + (mx - rectFrom.xmin) * rw;
395  y = rectTo.ymin + (my - rectFrom.ymin) * rh;
396}
397
398void 
399GRectMapper::unmap(int &x, int &y)
400{
401  // precalc
402  if (! (rw.p && rh.p))
403    precalc();
404  // scale and translate
405  int mx = rectFrom.xmin + (x - rectTo.xmin) / rw;
406  int my = rectFrom.ymin + (y - rectTo.ymin) / rh;
407  //  mirror and swap
408  if (code & MIRRORX)
409    mx = rectFrom.xmin + rectFrom.xmax - mx;
410  if (code & MIRRORY)
411    my = rectFrom.ymin + rectFrom.ymax - my;
412  if (code & SWAPXY)
413    iswap(mx,my);
414  x = mx;
415  y = my;
416}
417
418void 
419GRectMapper::map(GRect &rect)
420{
421  map(rect.xmin, rect.ymin);
422  map(rect.xmax, rect.ymax);
423  if (rect.xmin >= rect.xmax)
424    iswap(rect.xmin, rect.xmax);
425  if (rect.ymin >= rect.ymax)
426    iswap(rect.ymin, rect.ymax);
427}
428
429void 
430GRectMapper::unmap(GRect &rect)
431{
432  unmap(rect.xmin, rect.ymin);
433  unmap(rect.xmax, rect.ymax);
434  if (rect.xmin >= rect.xmax)
435    iswap(rect.xmin, rect.xmax);
436  if (rect.ymin >= rect.ymax)
437    iswap(rect.ymin, rect.ymax);
438}
439
440GRect
441GRectMapper::get_input()
442{
443    return rectFrom;
444}
445
446GRect
447GRectMapper::get_output()
448{
449    return rectTo;
450}
451
452
453#ifdef HAVE_NAMESPACES
454}
455# ifndef NOT_USING_DJVU_NAMESPACE
456using namespace DJVU;
457# endif
458#endif
Note: See TracBrowser for help on using the repository browser.