1
// =============================================================== //
3
// File : AW_device.cxx //
6
// Institute of Microbiology (Technical University Munich) //
7
// http://www.arb-home.de/ //
9
// =============================================================== //
11
#include "aw_window.hxx"
7
12
#include "aw_root.hxx"
8
#include "aw_device.hxx"
9
#include "aw_window.hxx"
10
#include "aw_commn.hxx"
14
void AW_clip::set_cliprect(AW_rectangle *rect, bool allow_oversize) {
15
clip_rect = *rect; // coordintes : (0,0) = top-left-corner
17
if (clip_rect.t < common->screen.t) clip_rect.t = common->screen.t;
18
if (clip_rect.b > common->screen.b) clip_rect.b = common->screen.b;
19
if (clip_rect.l < common->screen.l) clip_rect.l = common->screen.l;
20
if (clip_rect.r > common->screen.r) clip_rect.r = common->screen.r;
24
bottom_font_overlap = 0;
25
left_font_overlap = 0;
26
right_font_overlap = 0;
28
if (allow_oversize) { // added 21.6.02 --ralf
29
if (clip_rect.t < common->screen.t) set_top_font_overlap(true);
30
if (clip_rect.b > common->screen.b) set_bottom_font_overlap(true);
31
if (clip_rect.l < common->screen.l) set_left_font_overlap(true);
32
if (clip_rect.r > common->screen.r) set_right_font_overlap(true);
36
int AW_clip::reduceClipBorders(int top, int bottom, int left, int right) {
37
// return 0 if no clipping area left
38
if (top > clip_rect.t) clip_rect.t = top;
39
if (bottom < clip_rect.b) clip_rect.b = bottom;
40
if (left > clip_rect.l) clip_rect.l = left;
41
if (right < clip_rect.r) clip_rect.r = right;
43
return !(clip_rect.b<clip_rect.t || clip_rect.r<clip_rect.l);
46
void AW_clip::reduce_top_clip_border(int top){
47
if (top > clip_rect.t) clip_rect.t = top;
50
void AW_clip::set_top_clip_border(int top, bool allow_oversize) {
53
if (clip_rect.t < common->screen.t) clip_rect.t = common->screen.t;
56
set_top_font_overlap(true); // added 21.6.02 --ralf
60
void AW_clip::reduce_bottom_clip_border(int bottom) {
61
if ( bottom < clip_rect.b) clip_rect.b = bottom;
64
void AW_clip::set_bottom_clip_border(int bottom, bool allow_oversize) {
67
if (clip_rect.b > common->screen.b) clip_rect.b = common->screen.b;
70
set_bottom_font_overlap(true); // added 21.6.02 --ralf
74
void AW_clip::set_bottom_clip_margin(int bottom,bool allow_oversize) {
75
clip_rect.b -= bottom;
77
if (clip_rect.b > common->screen.b) clip_rect.b = common->screen.b;
80
set_bottom_font_overlap(true); // added 21.6.02 --ralf
83
void AW_clip::reduce_left_clip_border(int left) {
84
if (left > clip_rect.l)clip_rect.l = left;
86
void AW_clip::set_left_clip_border(int left, bool allow_oversize) {
89
if (clip_rect.l < common->screen.l) clip_rect.l = common->screen.l;
92
set_left_font_overlap(true); // added 21.6.02 --ralf
96
void AW_clip::reduce_right_clip_border(int right) {
97
if (right < clip_rect.r) clip_rect.r = right;
100
void AW_clip::set_right_clip_border(int right, bool allow_oversize) {
102
if (!allow_oversize){
103
if (clip_rect.r > common->screen.r) clip_rect.r = common->screen.r;
106
set_right_font_overlap(true); // added to correct problem with last char skipped (added 21.6.02 --ralf)
110
void AW_clip::set_top_font_overlap(int val){
111
top_font_overlap = val;
113
void AW_clip::set_bottom_font_overlap(int val){
114
bottom_font_overlap = val;
116
void AW_clip::set_left_font_overlap(int val){
117
left_font_overlap = val;
119
void AW_clip::set_right_font_overlap(int val){
120
right_font_overlap = val;
124
memset((char *)this,0,sizeof(*this));
127
/**********************************************************************/
129
inline AW_pos clip_in_range(AW_pos low, AW_pos val, AW_pos high) {
130
if (val <= low) return low;
131
if (val >= high) return high;
135
int AW_clip::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)
136
// clip coordinates of a box
138
if (x1<clip_rect.l || x0>clip_rect.r) return 0;
139
if (y1<clip_rect.t || y0>clip_rect.b) return 0;
141
if (clip_rect.l>clip_rect.r) return 0;
142
if (clip_rect.t>clip_rect.b) return 0;
144
x0out = clip_in_range(clip_rect.l, x0, clip_rect.r);
145
x1out = clip_in_range(clip_rect.l, x1, clip_rect.r);
146
y0out = clip_in_range(clip_rect.t, y0, clip_rect.b);
147
y1out = clip_in_range(clip_rect.t, y1, clip_rect.b);
151
/**********************************************************************/
153
int AW_clip::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)
154
// clip coordinates of a line
160
bool is_visible = false; // indicates whether part of line is visible
161
bool done = false; // true soon as line is completely inside or outside rectangle
164
int outcode0 = compoutcode(x0,y0);
165
int outcode1 = compoutcode(x1,y1);
167
if ((outcode0 | outcode1) == 0) { // line is inside the rectangle
168
x0out = x0; y0out = y0; // clipped coordinates of line
169
x1out = x1; y1out = y1;
174
else if ((outcode0 & outcode1) != 0) { // line is outside the rectangle
177
else { // line overlaps with at least one rectangle border
178
outcodeout = outcode0>0 ? outcode0 : outcode1;
180
if ((outcodeout & 8) != 0) { // overlap at top
181
x = x0+(x1-x0)*(clip_rect.t-y0)/(y1-y0);
184
else if ((outcodeout & 4) != 0) { // overlap at bottom
185
x = x0+(x1-x0)*(clip_rect.b-y0)/(y1-y0);
188
else if ((outcodeout & 2) != 0) { // overlap at right side
189
y = y0+(y1-y0)*(clip_rect.r-x0)/(x1-x0);
192
else if ((outcodeout & 1) != 0) {
193
y = y0+(y1-y0)*(clip_rect.l-x0)/(x1-x0); // overlap at left side
197
// set corrected point and iterate :
212
void AW_matrix::zoom(AW_pos val) {
217
void AW_matrix::reset(void) {
218
unscale = scale = 1.0;
219
offset = AW::Vector(0, 0);
222
/**********************************************************************************************
224
**********************************************************************************************/
225
AW_GC_Xm::AW_GC_Xm(AW_common *commoni) {
235
unsigned long value_mask = GCLineWidth;
237
gc = XCreateGC(common->display,common->window_id,value_mask,&val);
241
AW_GC_Xm::~AW_GC_Xm(void) {
242
if (gc) XFreeGC(common->display,gc);
246
void AW_GC_Xm::set_fill(AW_grey_level grey_leveli) { // <0 dont fill 0.0 white 1.0 black
247
grey_level = grey_leveli;
251
void AW_GC_Xm::set_lineattributes(AW_pos width,AW_linestyle stylei) {
252
int lwidth = AW_INT(width);
253
if (stylei == style && line_width == lwidth) return;
257
XSetLineAttributes(common->display, gc, lwidth, LineSolid, CapButt, JoinBevel);
260
XSetLineAttributes(common->display, gc, lwidth, LineOnOffDash, CapButt, JoinBevel);
270
void AW_GC_Xm::set_function(AW_function mode)
272
if (function != mode) {
275
XSetFunction(common->display,gc,GXxor);
278
XSetFunction(common->display,gc,GXcopy);
282
set_foreground_color(color);
286
void AW_GC_Xm::set_foreground_color(unsigned long col) {
288
if (function == AW_XOR) {
289
if (common->data_colors[0]) {
290
col ^= common->data_colors[0][AW_DATA_BG];
292
col ^= common->frame_colors[AW_WINDOW_BG];
295
XSetForeground(common->display,gc, col );
299
void AW_GC_Xm::set_background_color(unsigned long colori) {
300
XSetBackground(common->display,gc, colori );
301
last_bg_color = colori;
304
const AW_font_information *AW_gc::get_font_information(int gc, unsigned char c) {
305
AW_GC_Xm *gcm = (common->gcs[gc]);
306
AW_font_information *ptr = &common->gcs[gc]->fontinfo;
308
ptr->this_letter.ascent = gcm->ascent_of_chars[c];
309
ptr->this_letter.descent = gcm->descent_of_chars[c];
310
ptr->this_letter.width = gcm->width_of_chars[c];
311
ptr->this_letter.calc_height();
316
/**********************************************************************************************
318
**********************************************************************************************/
320
int AW_gc::get_string_size(int gc, const char *str, long textlen) {
321
// get the size of the string
322
XFontStruct *xfs = &common->gcs[gc]->curfont;
323
short *size_per_char = common->gcs[gc]->width_of_chars;
326
textlen = strlen(str);
331
if (xfs->max_bounds.width == xfs->min_bounds.width || !str) {
333
l_width = textlen * xfs->max_bounds.width;
335
else { // non-monospaced font
337
for (c = *(str++); c; c = *(str++)) {
338
l_width += size_per_char[c];
343
void AW_gc::new_gc(int gc) {
344
if (gc>= common->ngcs) {
345
common->gcs = (AW_GC_Xm **)realloc((char *)common->gcs,sizeof(void *)*(gc+10));
346
memset( &common->gcs[common->ngcs],0,sizeof(void *) * (gc-common->ngcs+10));
347
common->ngcs = gc+10;
349
if (common->gcs[gc])delete (common->gcs[gc]);
350
common->gcs[gc] = new AW_GC_Xm(common);
354
void AW_gc::set_fill(int gc,AW_grey_level grey_level){
355
aw_assert(common->gcs[gc]);
356
common->gcs[gc]->set_fill(grey_level);}
359
void AW_gc::set_font(int gc,AW_font font_nr, int size, int *found_size) {
360
// if found_size != 0 -> return value for used font size
361
aw_assert(common->gcs[gc]);
362
common->gcs[gc]->set_font(font_nr, size, found_size);
365
int AW_gc::get_available_fontsizes(int gc, AW_font font_nr, int *available_sizes) {
366
aw_assert(common->gcs[gc]);
367
return common->gcs[gc]->get_available_fontsizes(font_nr, available_sizes);
371
void AW_gc::set_line_attributes(int gc,AW_pos width,AW_linestyle style){
372
aw_assert(common->gcs[gc]);
373
common->gcs[gc]->set_lineattributes(width,style);
377
void AW_gc::set_function(int gc,AW_function function){
378
aw_assert(common->gcs[gc]);
379
common->gcs[gc]->set_function(function);
383
void AW_gc::set_foreground_color(int gc, AW_color color) {
385
if (color>=AW_DATA_BG) {
386
col = common->data_colors[0][color];
388
col = common->frame_colors[color];
390
common->gcs[gc]->set_foreground_color(col);
394
void AW_gc::set_background_color(int gc, AW_color color) {
396
if (color>=AW_DATA_BG) {
397
col = common->data_colors[0][color];
399
col = common->frame_colors[color];
401
common->gcs[gc]->set_background_color(col);
406
/**********************************************************************************************
408
**********************************************************************************************/
409
void AW_get_common_extends_cb(AW_window *aww,AW_common *common) {
412
unsigned int width,height;
413
unsigned int depth, borderwidth;
415
XGetGeometry(common->display,common->window_id,
417
&common->screen_x_offset, // xoffset
418
&common->screen_y_offset, // yoffset
421
&borderwidth, // border width
422
&depth); // depth of display
424
common->screen.t = 0; // set clipping coordinates
425
common->screen.b = height;
426
common->screen.l = 0;
427
common->screen.r = width;
430
AW_common::AW_common(AW_window *aww, AW_area area, Display *display_in,
431
XID window_id_in,unsigned long *fcolors,
432
unsigned int **dcolors, long *data_colors_size_in)
434
memset((char *)this,0,sizeof(AW_common));
436
root = aww->get_root();
437
window_id = window_id_in;
438
display = display_in;
439
frame_colors = fcolors;
440
data_colors = (unsigned long **)dcolors;
441
data_colors_size = data_colors_size_in;
443
gcs = (AW_GC_Xm **)malloc(sizeof(void *)*ngcs);
445
memset((char *)gcs,0,sizeof(void *)*ngcs);
446
aww->set_resize_callback(area,(AW_CB2)AW_get_common_extends_cb,(AW_CL)this,0);
447
AW_get_common_extends_cb(aww,this);
450
/**********************************************************************************************
452
**********************************************************************************************/
454
// ----------------------------
455
// AW_clip_scale_stack
456
// ----------------------------
13
#include "aw_common_xm.hxx"
458
17
#if defined(DEBUG)
459
18
// #define SHOW_CLIP_STACK_CHANGES
463
22
// completely private, but accessible by AW_device
464
23
friend class AW_device;
466
AW_rectangle clip_rect;
468
int top_font_overlap;
469
int bottom_font_overlap;
470
int left_font_overlap;
471
int right_font_overlap;
25
AW_screen_area clip_rect;
26
AW_font_overlap font_overlap;
473
28
AW::Vector offset;
476
31
class AW_clip_scale_stack *next;
479
34
#if defined(SHOW_CLIP_STACK_CHANGES)
480
35
static const char *clipstatestr(AW_device *device) {
481
static char buffer[1024];
482
AW_rectangle& clip_rect = device->clip_rect;
484
sprintf(buffer, "clip_rect={t=%i, b=%i, l=%i, r=%i}",
485
clip_rect.t, clip_rect.b, clip_rect.l, clip_rect.r);
36
static char buffer[1024];
38
const AW_screen_area& clip_rect = device->get_cliprect();
39
const AW_font_overlap& fo = device->get_font_overlap();
40
const AW::Vector& offset = device->get_offset();
43
"clip_rect={t=%i, b=%i, l=%i, r=%i} "
44
"font_overlap={t=%i, b=%i, l=%i, r=%i} "
45
"scale=%f unscale=%f "
46
"offset={x=%f y=%f}" ,
47
clip_rect.t, clip_rect.b, clip_rect.l, clip_rect.r,
48
fo.top, fo.bottom, fo.left, fo.right,
49
device->get_scale(), device->get_unscale(),
50
offset.x(), offset.y());
489
54
#endif // SHOW_CLIP_STACK_CHANGES
493
void AW_device::push_clip_scale(void)
495
AW_clip_scale_stack *stack = new AW_clip_scale_stack;
497
stack->next = clip_scale_stack;
498
clip_scale_stack = stack;
500
stack->scale = get_scale();
501
stack->offset = get_offset();
503
stack->top_font_overlap = top_font_overlap;
504
stack->bottom_font_overlap = bottom_font_overlap;
505
stack->left_font_overlap = left_font_overlap;
506
stack->right_font_overlap = right_font_overlap;
508
stack->clip_rect = clip_rect;
510
#if defined(SHOW_CLIP_STACK_CHANGES)
511
printf("push_clip_scale: %s\n", clipstatestr(this));
512
#endif // SHOW_CLIP_STACK_CHANGES
56
const AW_screen_area& AW_device::get_area_size() const {
57
return get_common()->get_screen();
514
void AW_device::pop_clip_scale(void){
61
void AW_device::pop_clip_scale() {
515
62
if (!clip_scale_stack) {
516
AW_ERROR("Too many pop_clip_scale on that device");
63
aw_assert(0); // Too many pop_clip_scale on that device
521
68
char *state_before_pop = strdup(clipstatestr(this));
522
69
#endif // SHOW_CLIP_STACK_CHANGES
72
set_offset(clip_scale_stack->offset); // needs to be called before zoom()
524
73
zoom(clip_scale_stack->scale);
525
set_offset(clip_scale_stack->offset);
527
clip_rect = clip_scale_stack->clip_rect;
529
top_font_overlap = clip_scale_stack->top_font_overlap;
530
bottom_font_overlap = clip_scale_stack->bottom_font_overlap;
531
left_font_overlap = clip_scale_stack->left_font_overlap;
532
right_font_overlap = clip_scale_stack->right_font_overlap;
74
set_cliprect(clip_scale_stack->clip_rect);
75
set_font_overlap(clip_scale_stack->font_overlap);
77
aw_assert(get_scale() == clip_scale_stack->scale);
534
79
AW_clip_scale_stack *oldstack = clip_scale_stack;
535
80
clip_scale_stack = clip_scale_stack->next;
538
83
#if defined(SHOW_CLIP_STACK_CHANGES)
539
printf("pop_clip_scale: %s -> %s\n", state_before_pop, clipstatestr(this));
84
printf(" pop_clip_scale: %s\n", state_before_pop);
85
printf(" [after pop]: %s\n\n", clipstatestr(this));
540
86
free(state_before_pop);
541
87
#endif // SHOW_CLIP_STACK_CHANGES
544
// --------------------------------------------------------------------------------
546
void AW_device::get_area_size(AW_rectangle *rect) { //get the extends from the class AW_device
547
*rect = common->screen;
550
void AW_device::get_area_size(AW_world *rect) { //get the extends from the class AW_device
551
rect->t = common->screen.t;
552
rect->b = common->screen.b;
553
rect->l = common->screen.l;
554
rect->r = common->screen.r;
557
AW::Rectangle AW_device::get_area_size() {
558
AW_rectangle& scr = common->screen;
559
return AW::Rectangle(scr.l, scr.t, scr.r, scr.b);
562
void AW_device::privat_reset() {}
564
void AW_device::reset(){
565
while (clip_scale_stack){
568
get_area_size(&clip_rect);
573
AW_device::AW_device(class AW_common *commoni) : AW_gc(){
575
clip_scale_stack = 0;
576
filter = (AW_bitset)-1;
579
AW_gc::AW_gc() : AW_clip() {}
581
/**********************************************************************************************
583
**********************************************************************************************/
585
bool AW_device::invisible(int gc, AW_pos x, AW_pos y, AW_bitset filteri, AW_CL clientdata1, AW_CL clientdata2) {
586
AWUSE(clientdata1);AWUSE(clientdata2);
588
if(filteri & filter) {
589
AW_pos X,Y; // Transformed pos
591
return ! (X<clip_rect.l || X>clip_rect.r ||
592
Y<clip_rect.t || Y>clip_rect.b);
597
bool AW_device::ready_to_draw(int gc) {
598
return AW_GC_MAPABLE(common, gc);
601
// PJ: ::zoomtext is defined in AW_xfigfont.cxx
603
int AW_device::generic_box(int gc, bool /*filled*/, AW_pos x0,AW_pos y0,AW_pos width,AW_pos height, AW_bitset filteri, AW_CL cd1, AW_CL cd2)
606
if (filteri & filter) {
607
erg |= line(gc,x0,y0,x0+width,y0,filteri,cd1,cd2);
608
erg |= line(gc,x0,y0,x0,y0+height,filteri,cd1,cd2);
609
erg |= line(gc,x0+width,y0+height,x0+width,y0+height,filteri,cd1,cd2);
610
erg |= line(gc,x0+width,y0+height,x0+width,y0+height,filteri,cd1,cd2);
615
#if defined(DEVEL_RALF)
616
#warning draw in 45-degree-steps (8-cornered-polygones instead of circles)
619
int AW_device::generic_circle(int gc, bool /*filled has no effect here*/, AW_pos x0,AW_pos y0,AW_pos width,AW_pos height, AW_bitset filteri, AW_CL cd1, AW_CL cd2)
622
if (filteri & filter) {
623
erg |= line(gc,x0,y0+height,x0+width,y0,filteri,cd1,cd2);
624
erg |= line(gc,x0,y0+height,x0-width,y0,filteri,cd1,cd2);
625
erg |= line(gc,x0,y0-height,x0+width,y0,filteri,cd1,cd2);
626
erg |= line(gc,x0,y0-height,x0-width,y0,filteri,cd1,cd2);
631
int AW_device::generic_arc(int gc, bool /*filled has no effect here*/, AW_pos x0,AW_pos y0,AW_pos width,AW_pos height, int /*start_degrees*/, int /*arc_degrees*/, AW_bitset filteri, AW_CL cd1, AW_CL cd2)
634
if (filteri & filter) {
635
erg |= line(gc,x0,y0+height,x0+width,y0,filteri,cd1,cd2);
636
erg |= line(gc,x0,y0+height,x0-width,y0,filteri,cd1,cd2);
637
erg |= line(gc,x0,y0-height,x0+width,y0,filteri,cd1,cd2);
638
erg |= line(gc,x0,y0-height,x0-width,y0,filteri,cd1,cd2);
642
int AW_device::generic_filled_area(int gc, int npoints, AW_pos *points, AW_bitset filteri, AW_CL cd1, AW_CL cd2){
644
if (filteri & filter) {
646
erg |= line(gc,points[0],points[1],points[npoints*2],points[npoints*2+1],filteri,cd1,cd2);
648
AW_pos x = *(points++);
649
AW_pos y = *(points++);
650
erg |= line(gc,x,y,points[0],points[1],filteri,cd1,cd2);
658
void AW_device::clear(AW_bitset /*filteri*/) {}
659
void AW_device::clear_part(AW_pos /*x*/, AW_pos /*y*/, AW_pos /*width*/, AW_pos /*height*/, AW_bitset /*filteri*/) {}
660
void AW_device::clear_text(int /*gc*/, const char */*string*/, AW_pos /*x*/, AW_pos /*y*/, AW_pos /*alignment*/, AW_bitset /*filteri*/, AW_CL /*cd1*/, AW_CL /*cd2*/) {}
661
void AW_device::move_region( AW_pos /*src_x*/, AW_pos /*src_y*/, AW_pos /*width*/, AW_pos /*height*/, AW_pos /*dest_x*/, AW_pos /*dest_y*/ ) {}
662
void AW_device::fast(void) {}
663
void AW_device::slow(void) {}
664
void AW_device::flush(void) {}
666
// forbidden operations:
667
static void forbidden(const char *toUse) { AW_ERROR("It's not allowed to use '%s' with this device", toUse); }
668
const char *AW_device::open(const char */*path*/) { forbidden("open"); return 0; }
669
void AW_device::close(void) { forbidden("close"); }
670
void AW_device::set_color_mode(bool /*mode*/) { forbidden("set_color_mode"); }
671
void AW_device::get_clicked_line(AW_clicked_line */*ptr*/) { forbidden("get_clicked_line"); }
672
void AW_device::get_clicked_text(AW_clicked_text */*ptr*/) { forbidden("get_clicked_text"); }
673
void AW_device::get_size_information(AW_world */*ptr*/) { forbidden("get_size_information"); }
675
int AW_device::cursor(int gc, AW_pos x0,AW_pos y0, AW_cursor_type cur_type, AW_bitset filteri, AW_CL clientdata1, AW_CL clientdata2) {
676
class AW_GC_Xm *gcm = AW_MAP_GC(gc);
677
XFontStruct *xfs = &gcm->curfont;
679
AW_pos X0,Y0; // Transformed pos
681
// cursor insert cursor overwrite
688
if(filteri & filter) {
689
if( cur_type == AW_cursor_insert ) {
690
transform(x0,y0,X0,Y0);
692
if (X0 > clip_rect.r) return 0;
693
if (X0 < clip_rect.l) return 0;
694
if (Y0+(AW_pos)(xfs->max_bounds.descent) < clip_rect.t) return 0;
695
if (Y0-(AW_pos)(xfs->max_bounds.ascent) > clip_rect.b) return 0;
702
line(gc,x1,y1,x0,y0,filteri,clientdata1, clientdata2);
703
line(gc,x2,y2,x0,y0,filteri,clientdata1, clientdata2);
704
line(gc,x1,y1,x2,y2,filteri,clientdata1, clientdata2);
710
int AW_device::text_overlay( int gc, const char *opt_str, long opt_len, // either string or strlen != 0
711
AW_pos x,AW_pos y, AW_pos alignment, AW_bitset filteri, AW_CL cduser, AW_CL cd1, AW_CL cd2,
712
AW_pos opt_ascent,AW_pos opt_descent, // optional height (if == 0 take font height)
713
int (*f)(AW_device *device, int gc, const char *opt_string, size_t opt_string_len,size_t start, size_t size,
714
AW_pos x,AW_pos y, AW_pos opt_ascent,AW_pos opt_descent,
715
AW_CL cduser, AW_CL cd1, AW_CL cd2))
718
AW_GC_Xm *gcm = AW_MAP_GC(gc);
719
XFontStruct *xfs = &gcm->curfont;
720
short *size_per_char = common->gcs[gc]->width_of_chars;
726
AW_pos X0,Y0; // Transformed pos
90
void AW_device::push_clip_scale() {
91
AW_clip_scale_stack *stack = new AW_clip_scale_stack;
93
stack->next = clip_scale_stack;
94
clip_scale_stack = stack;
96
stack->scale = get_scale();
97
stack->offset = get_offset();
98
stack->font_overlap = get_font_overlap();
99
stack->clip_rect = get_cliprect();
101
#if defined(SHOW_CLIP_STACK_CHANGES)
102
printf("push_clip_scale: %s\n", clipstatestr(this));
103
#endif // SHOW_CLIP_STACK_CHANGES
106
bool AW_device::text_overlay(int gc, const char *opt_str, long opt_len, // either string or strlen != 0
107
const AW::Position& pos, AW_pos alignment, AW_bitset filteri, AW_CL cduser,
108
AW_pos opt_ascent, AW_pos opt_descent, // optional height (if == 0 take font height)
109
TextOverlayCallback toc)
111
const AW_GC *gcm = get_common()->map_gc(gc);
112
const AW_font_limits& font_limits = gcm->get_font_limits();
119
AW_pos X0, Y0; // Transformed pos
728
121
bool inside_clipping_left = true; // clipping at the left edge of the screen is different from clipping right of the left edge.
729
122
bool inside_clipping_right = true;
737
130
if (!(filter & filteri)) return 0;
739
if (left_font_overlap || common->screen.l == clip_rect.l) { // was : clip_rect.l == 0
740
inside_clipping_left = false;
743
if (right_font_overlap || clip_rect.r == common->screen.r) { // was : clip_rect.r == common->screen.r
745
inside_clipping_right = false;
748
transform(x,y,X0,Y0);
751
if (top_font_overlap || clip_rect.t == 0) { // check clip border inside screen
752
if (Y0+(AW_pos)(xfs->max_bounds.descent) < clip_rect.t) return 0; // draw outside screen
754
if (Y0-(AW_pos)(xfs->max_bounds.ascent) < clip_rect.t) return 0; // dont cross the clip border
757
if (bottom_font_overlap || clip_rect.b == common->screen.b) { // check clip border inside screen drucken
758
if (Y0-(AW_pos)(xfs->max_bounds.ascent) > clip_rect.b) return 0; // draw outside screen
760
if (Y0+(AW_pos)(xfs->max_bounds.descent)> clip_rect.b) return 0; // dont cross the clip border
132
const AW_screen_area& screen = get_common()->get_screen();
133
const AW_screen_area& clipRect = get_cliprect();
135
if (allow_left_font_overlap() || screen.l == clipRect.l) inside_clipping_left = false;
136
if (allow_right_font_overlap() || clipRect.r == screen.r) inside_clipping_right = false;
138
transform(pos.xpos(), pos.ypos(), X0, Y0);
140
if (allow_top_font_overlap() || clipRect.t == 0) { // check clip border inside screen
141
if (Y0+font_limits.descent < clipRect.t) return 0; // draw outside screen
144
if (Y0-font_limits.ascent < clipRect.t) return 0; // don't cross the clip border
147
if (allow_bottom_font_overlap() || clipRect.b == screen.b) { // check clip border inside screen
148
if (Y0-font_limits.ascent > clipRect.b) return 0; // draw outside screen
151
if (Y0+font_limits.descent> clipRect.b) return 0; // don't cross the clip border
764
155
opt_len = textlen = strlen(opt_str);
766
158
textlen = opt_len;
769
161
aw_assert(opt_len == textlen);
770
aw_assert(int(strlen(opt_str)) >= textlen);
773
AW_pos width = get_string_size(gc,opt_str,textlen);
165
int opt_str_len = int(strlen(opt_str));
166
aw_assert(opt_str_len >= textlen);
170
AW_pos width = get_string_size(gc, opt_str, textlen);
774
171
X0 = X0-alignment*width;
778
if (X0 > clip_rect.r) return 0; // right of screen
174
if (X0 > clipRect.r) return 0; // right of screen
780
l = (int)clip_rect.l;
781
if (xi + textlen*xfs->max_bounds.width < l) return 0; // left of screen
177
if (xi + textlen*font_limits.width < l) return 0; // left of screen
784
if (xi < l) { // now clip left side
785
if (xfs->max_bounds.width == xfs->min_bounds.width) { // monospaced font
786
h = (l - xi)/xfs->max_bounds.width;
181
// now clip left side
183
if (font_limits.is_monospaced()) {
184
h = (l - xi)/font_limits.width;
787
185
if (inside_clipping_left) {
788
if ( (l-xi)%xfs->max_bounds.width >0 ) h += 1;
186
if ((l-xi)%font_limits.width >0) h += 1;
790
188
if (h >= textlen) return 0;
792
xi += h*xfs->max_bounds.width;
190
xi += h*font_limits.width;
795
193
if (textlen < 0) return 0;
796
194
aw_assert(int(strlen(opt_str)) >= textlen);
797
}else { // non-monospaced font
196
else { // proportional font
798
198
for (h=0; xi < l; h++) {
799
199
if (!(c = opt_str[h])) return 0;
800
xi += size_per_char[c];
200
xi += gcm->get_width_of_char(c);
802
202
if (!inside_clipping_left) {
804
xi -= size_per_char[c];
204
xi -= gcm->get_width_of_char(c);
839
240
aw_assert(int(strlen(opt_str)) >= textlen);
842
rtransform(X0,Y0,x,y);
245
rtransform(X0, Y0, corrx, corry);
844
247
aw_assert(opt_len >= textlen);
845
248
aw_assert(textlen >= 0 && int(strlen(opt_str)) >= textlen);
847
return f(this,gc,opt_str,opt_len, start ,(size_t)textlen, x,y, opt_ascent, opt_descent, cduser, cd1, cd2);
850
/**********************************************************************************************
852
**********************************************************************************************/
854
void AW_device::set_filter(AW_bitset filteri) { filter = filteri; }
250
return toc(this, gc, opt_str, opt_len, start, (size_t)textlen, corrx, corry, opt_ascent, opt_descent, cduser);
253
bool AW_device::generic_filled_area(int gc, int npos, const AW::Position *pos, AW_bitset filteri) {
254
bool drawflag = false;
255
if (filteri & filter) {
257
for (int n = 0; n<npos; ++n) {
258
drawflag |= line(gc, pos[p], pos[n], filteri);
265
void AW_device::move_region(AW_pos /* src_x */, AW_pos /* src_y */, AW_pos /* width */, AW_pos /* height */,
266
AW_pos /* dest_x */, AW_pos /* dest_y */) {
270
void AW_device::flush() {
274
static const AW_screen_area& get_universe() {
275
// "unrestricted" area
276
const int UMIN = INT_MIN/10;
277
const int UMAX = INT_MAX/10;
278
static AW_screen_area universe = { UMIN, UMAX, UMIN, UMAX };
282
void AW_device::reset() {
283
while (clip_scale_stack) {
286
if (type() == AW_DEVICE_SIZE) {
287
set_cliprect(get_universe());
290
set_cliprect(get_area_size());
292
AW_zoomable::reset();
296
bool AW_device::generic_invisible(const AW::Position& pos, AW_bitset filteri) {
297
return (filter & filteri) ? !is_outside_clip(transform(pos)) : false;
300
const AW_screen_area& AW_device::get_common_screen(const AW_common *common_) {
301
return common_->get_screen();
304
bool AW_device::generic_box(int gc, bool /*filled*/, const AW::Rectangle& rect, AW_bitset filteri) {
305
// Note: 'filled' is not supported on this device
307
if (filteri & filter) {
308
drawflag |= line_impl(gc, rect.upper_edge(), filteri);
309
drawflag |= line_impl(gc, rect.lower_edge(), filteri);
310
drawflag |= line_impl(gc, rect.left_edge(), filteri);
311
drawflag |= line_impl(gc, rect.right_edge(), filteri);
316
void AW_device::clear(AW_bitset) {
320
void AW_device::clear_part(const AW::Rectangle&, AW_bitset) {
324
void AW_device::set_filter(AW_bitset filteri) {
328
void AW_device::fast() {}
329
void AW_device::slow() {}
330
bool AW_device::ready_to_draw(int gc) {
331
return get_common()->gc_mapable(gc);
334
void AW_zoomable::reset() {
335
unscale = scale = 1.0;
336
offset = AW::Vector(0, 0);
339
void AW_zoomable::zoom(AW_pos val) {
347
const int GC_DEFAULT_LINE_STYLE = LineSolid;
348
const int GC_DEFAULT_CAP_STYLE = CapProjecting;
349
const int GC_JOIN_STYLE = JoinMiter;
351
AW_GC_Xm::AW_GC_Xm(AW_common *common_)
356
val.line_width = GC_DEFAULT_LINE_WIDTH;
357
val.line_style = GC_DEFAULT_LINE_STYLE;
358
val.cap_style = GC_DEFAULT_CAP_STYLE;
359
val.join_style = GC_JOIN_STYLE;
361
unsigned long value_mask = GCLineWidth|GCLineStyle|GCCapStyle|GCJoinStyle;
363
gc = XCreateGC(get_common()->get_display(), get_common()->get_window_id(), value_mask, &val);
364
wm_set_function(get_function());
366
AW_GC_Xm::~AW_GC_Xm() {
367
if (gc) XFreeGC(get_common()->get_display(), gc);
369
void AW_GC_Xm::wm_set_lineattributes(short lwidth, AW_linestyle lstyle) {
370
Display *display = get_common()->get_display();
375
XSetLineAttributes(display, gc, lwidth, LineSolid, GC_DEFAULT_CAP_STYLE, GC_JOIN_STYLE);
380
static char dashes[] = { 5, 2 };
381
static char dots[] = { 1, 1 };
382
XSetDashes(display, gc, 0, lstyle == AW_DOTTED ? dots : dashes, 2);
383
XSetLineAttributes(display, gc, lwidth, LineOnOffDash, CapButt, GC_JOIN_STYLE);
388
void AW_GC_Xm::wm_set_function(AW_function mode) {
391
XSetFunction(get_common()->get_display(), gc, GXxor);
394
XSetFunction(get_common()->get_display(), gc, GXcopy);
398
void AW_GC_Xm::wm_set_foreground_color(AW_rgb col) {
399
XSetForeground(get_common()->get_display(), gc, col);
402
const AW_font_limits& AW_stylable::get_font_limits(int gc, char c) const {
403
return get_common()->get_font_limits(gc, c);
406
int AW_GC::get_string_size(const char *str, long textlen) const {
407
// calculate display size of 'str'
408
// 'str' and/or 'textlen' may be 0
409
// 'str' == 0 -> calculate max width of any text with length 'textlen'
410
// 'textlen' == 0 -> calls strlen when needed
411
// both 0 -> return 0
414
if (font_limits.is_monospaced() || !str) {
415
if (!textlen && str) textlen = strlen(str);
416
width = textlen * font_limits.width;
419
for (int c = *(str++); c; c = *(str++)) width += width_of_chars[c];
424
AW_GC *AW_common_Xm::create_gc() {
425
return new AW_GC_Xm(this);
428
void AW_GC_set::add_gc(int gi, AW_GC *agc) {
430
int new_count = gi+10;
431
realloc_unleaked(gcs, sizeof(*gcs)*new_count);
432
if (!gcs) GBK_terminate("out of memory");
433
memset(&gcs[count], 0, sizeof(*gcs)*(new_count-count));
436
if (gcs[gi]) delete gcs[gi];
440
int AW_stylable::get_string_size(int gc, const char *str, long textlen) const {
441
return get_common()->map_gc(gc)->get_string_size(str, textlen);
443
void AW_stylable::new_gc(int gc) { get_common()->new_gc(gc); }
444
void AW_stylable::set_grey_level(int gc, AW_grey_level grey_level) {
445
// <0 = don't fill, 0.0 = white, 1.0 = black
446
get_common()->map_mod_gc(gc)->set_grey_level(grey_level);
448
void AW_stylable::set_font(int gc, AW_font font_nr, int size, int *found_size) {
449
// if found_size != 0 -> return value for used font size
450
get_common()->map_mod_gc(gc)->set_font(font_nr, size, found_size);
452
int AW_stylable::get_available_fontsizes(int gc, AW_font font_nr, int *available_sizes) {
453
return get_common()->map_gc(gc)->get_available_fontsizes(font_nr, available_sizes);
455
void AW_stylable::set_line_attributes(int gc, short width, AW_linestyle style) {
456
get_common()->map_mod_gc(gc)->set_line_attributes(width, style);
458
void AW_stylable::set_function(int gc, AW_function function) {
459
get_common()->map_mod_gc(gc)->set_function(function);
461
void AW_stylable::set_foreground_color(int gc, AW_color_idx color) {
462
get_common()->map_mod_gc(gc)->set_fg_color(get_common()->get_color(color));
464
void AW_stylable::establish_default(int gc) {
465
get_common()->map_mod_gc(gc)->establish_default();
467
void AW_stylable::reset_style() {
468
get_common()->reset_style();
471
static void AW_get_common_extends_cb(AW_window *, AW_common_Xm *common) {
473
unsigned int width, height;
474
unsigned int depth, borderwidth; // unused
475
int x_offset, y_offset; // unused
477
XGetGeometry(common->get_display(), common->get_window_id(),
483
&borderwidth, // border width
484
&depth); // depth of display
486
common->set_screen_size(width, height);
489
void AW_common_Xm::install_common_extends_cb(AW_window *aww, AW_area area) {
490
aww->set_resize_callback(area, makeWindowCallback(AW_get_common_extends_cb, this));
491
AW_get_common_extends_cb(aww, this);