source: trunk/libdjvu/GRect.cpp @ 280

Last change on this file since 280 was 280, checked in by rbri, 11 years ago

DJVU plugin: djvulibre updated to version 3.5.22

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