source: branches/profile/WINDOW/AW_clipable.cxx

Last change on this file was 10240, checked in by westram, 11 years ago
  • move more code around like done in gtk-branch (to ease merging; only performed minimal changes)
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 7.4 KB
Line 
1// =============================================================== //
2//                                                                 //
3//   File      : AW_clipable.cxx                                   //
4//   Purpose   :                                                   //
5//                                                                 //
6//   Institute of Microbiology (Technical University Munich)       //
7//   http://www.arb-home.de/                                       //
8//                                                                 //
9// =============================================================== //
10
11#include "aw_window.hxx"
12#include "aw_root.hxx"
13#include "aw_common_xm.hxx"
14
15#include <arb_msg.h>
16
17using namespace AW;
18
19inline AW_pos clip_in_range(AW_pos low, AW_pos val, AW_pos high) {
20    if (val <= low) return low;
21    if (val >= high) return high;
22    return val;
23}
24
25bool AW_clipable::box_clip(AW_pos x0, AW_pos y0, AW_pos x1, AW_pos y1, AW_pos& x0out, AW_pos& y0out, AW_pos& x1out, AW_pos& y1out) {
26    // clip coordinates of a box
27
28    aw_assert(x0 <= x1);
29    aw_assert(y0 <= y1);
30
31    if (x1<clip_rect.l || x0>clip_rect.r) return false;
32    if (y1<clip_rect.t || y0>clip_rect.b) return false;
33
34    if (completely_clipped()) return false;
35
36    x0out = clip_in_range(clip_rect.l, x0, clip_rect.r);
37    x1out = clip_in_range(clip_rect.l, x1, clip_rect.r);
38    y0out = clip_in_range(clip_rect.t, y0, clip_rect.b);
39    y1out = clip_in_range(clip_rect.t, y1, clip_rect.b);
40
41    return true;
42}
43
44bool AW_clipable::box_clip(const Rectangle& rect, Rectangle& clippedRect) { // @@@ maybe return clippedRect as AW_screen_area
45    if (completely_clipped()) return false;
46
47    Rectangle clipRect(clip_rect, UPPER_LEFT_OUTLINE);
48    if (rect.distinct_from(clipRect))
49        return false;
50
51    clippedRect = rect.intersect_with(clipRect);
52    return true;
53}
54
55
56bool AW_clipable::clip(AW_pos x0, AW_pos y0, AW_pos x1, AW_pos y1, AW_pos& x0out, AW_pos& y0out, AW_pos& x1out, AW_pos& y1out) {
57    // clip coordinates of a line
58
59    int    outcodeout;
60    AW_pos x = 0;
61    AW_pos y = 0;
62
63    bool is_visible = false;    // indicates whether part of line is visible
64    bool done       = false;    // true soon as line is completely inside or outside rectangle
65
66    while (!done) {
67        int outcode0 = compoutcode(x0, y0);
68        int outcode1 = compoutcode(x1, y1);
69
70        if ((outcode0 | outcode1) == 0) { // line is inside the rectangle
71            x0out = x0; y0out = y0; // clipped coordinates of line
72            x1out = x1; y1out = y1;
73
74            done    = true;
75            is_visible = true;
76        }
77        else if ((outcode0 & outcode1) != 0) { // line is outside the rectangle
78            done = true;
79        }
80        else { // line overlaps with at least one rectangle border
81            outcodeout = outcode0>0 ? outcode0 : outcode1;
82
83            if ((outcodeout & 8) != 0) { // overlap at top
84                x = x0+(x1-x0)*(clip_rect.t-y0)/(y1-y0);
85                y = clip_rect.t;
86            }
87            else if ((outcodeout & 4) != 0) { // overlap at bottom
88                x = x0+(x1-x0)*(clip_rect.b-y0)/(y1-y0);
89                y = clip_rect.b;
90            }
91            else if ((outcodeout & 2) != 0) { // overlap at right side
92                y = y0+(y1-y0)*(clip_rect.r-x0)/(x1-x0);
93                x = clip_rect.r;
94            }
95            else if ((outcodeout & 1) != 0) {
96                y = y0+(y1-y0)*(clip_rect.l-x0)/(x1-x0); // overlap at left side
97                x = clip_rect.l;
98            }
99
100            // set corrected point and iterate :
101            if (outcode0 > 0) {
102                x0 = x;
103                y0 = y;
104            }
105            else {
106                x1 = x;
107                y1 = y;
108            }
109        }
110    }
111
112    return is_visible;
113}
114
115bool AW_clipable::clip(const LineVector& line, LineVector& clippedLine) {
116    AW_pos x0, y0, x1, y1;
117    bool   drawflag = clip(line.start().xpos(), line.start().ypos(), line.head().xpos(), line.head().ypos(),
118                           x0, y0, x1, y1);
119    if (drawflag) clippedLine = LineVector(x0, y0, x1, y1);
120    return drawflag;
121}
122void AW_clipable::set_bottom_clip_border(int bottom, bool allow_oversize) {
123    clip_rect.b = bottom;
124    if (!allow_oversize) {
125        if (clip_rect.b > get_screen().b) clip_rect.b = get_screen().b;
126    }
127    else {
128        set_bottom_font_overlap(true); // added 21.6.02 --ralf
129    }
130}
131
132void AW_clipable::set_left_clip_border(int left, bool allow_oversize) {
133    clip_rect.l = left;
134    if (!allow_oversize) {
135        if (clip_rect.l < get_screen().l) clip_rect.l = get_screen().l;
136    }
137    else {
138        set_left_font_overlap(true); // added 21.6.02 --ralf
139    }
140}
141
142void AW_clipable::set_right_clip_border(int right, bool allow_oversize) {
143    clip_rect.r = right;
144    if (!allow_oversize) {
145        if (clip_rect.r > get_screen().r) clip_rect.r = get_screen().r;
146    }
147    else {
148        set_right_font_overlap(true); // added to correct problem with last char skipped (added 21.6.02 --ralf)
149    }
150}
151
152void AW_clipable::set_top_clip_border(int top, bool allow_oversize) {
153    clip_rect.t = top;
154    if (!allow_oversize) {
155        if (clip_rect.t < get_screen().t) clip_rect.t = get_screen().t;
156    }
157    else {
158        set_top_font_overlap(true); // added 21.6.02 --ralf
159    }
160}
161
162
163int AW_clipable::reduceClipBorders(int top, int bottom, int left, int right) {
164    // return 0 if no clipping area left
165    if (top    > clip_rect.t) clip_rect.t = top;
166    if (bottom < clip_rect.b) clip_rect.b = bottom;
167    if (left   > clip_rect.l) clip_rect.l = left;
168    if (right  < clip_rect.r) clip_rect.r = right;
169
170    return !(clip_rect.b<clip_rect.t || clip_rect.r<clip_rect.l);
171}
172
173void AW_clipable::set_cliprect_oversize(const AW_screen_area& rect, bool allow_oversize) {
174    clip_rect = rect;
175
176    const AW_screen_area& screen = get_screen();
177    if (!allow_oversize) {
178        if (clip_rect.t < screen.t) clip_rect.t = screen.t;
179        if (clip_rect.b > screen.b) clip_rect.b = screen.b;
180        if (clip_rect.l < screen.l) clip_rect.l = screen.l;
181        if (clip_rect.r > screen.r) clip_rect.r = screen.r;
182    }
183
184    set_font_overlap(false);
185
186    if (allow_oversize) { // added 21.6.02 --ralf
187        if (clip_rect.t < screen.t) set_top_font_overlap(true);
188        if (clip_rect.b > screen.b) set_bottom_font_overlap(true);
189        if (clip_rect.l < screen.l) set_left_font_overlap(true);
190        if (clip_rect.r > screen.r) set_right_font_overlap(true);
191    }
192}
193
194void AW_clipable::reduce_top_clip_border(int top) {
195    if (top > clip_rect.t) clip_rect.t = top;
196}
197void AW_clipable::reduce_bottom_clip_border(int bottom) {
198    if (bottom < clip_rect.b)     clip_rect.b = bottom;
199}
200void AW_clipable::reduce_left_clip_border(int left) {
201    if (left > clip_rect.l)clip_rect.l = left;
202}
203void AW_clipable::reduce_right_clip_border(int right) {
204    if (right < clip_rect.r)    clip_rect.r = right;
205}
206
207void AW_clipable::set_bottom_clip_margin(int bottom, bool allow_oversize) {
208    clip_rect.b -= bottom;
209    if (!allow_oversize) {
210        if (clip_rect.b > get_screen().b) clip_rect.b = get_screen().b;
211    }
212    else {
213        set_bottom_font_overlap(true); // added 21.6.02 --ralf
214    }
215}
216bool AW_clipable::force_into_clipbox(const Position& pos, Position& forcedPos) {
217    // force 'pos' inside 'clip_rect'
218    if (completely_clipped()) return false;
219
220    forcedPos.setx(clip_in_range(clip_rect.l, pos.xpos(), clip_rect.r));
221    forcedPos.sety(clip_in_range(clip_rect.t, pos.ypos(), clip_rect.b));
222    return true;
223}
224
Note: See TracBrowser for help on using the repository browser.