2 // "$Id: fl_line_style.cxx 8190 2011-01-05 10:21:45Z manolo $"
4 // Line style code for the Fast Light Tool Kit (FLTK).
6 // Copyright 1998-2010 by Bill Spitzak and others.
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Library General Public
10 // License as published by the Free Software Foundation; either
11 // version 2 of the License, or (at your option) any later version.
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Library General Public License for more details.
18 // You should have received a copy of the GNU Library General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
23 // Please report all bugs and problems on the following page:
25 // http://www.fltk.org/str.php
29 \file fl_line_style.cxx
30 \brief Line style drawing utility hiding different platforms.
34 #include <FL/fl_draw.H>
36 #include <FL/Fl_Printer.H>
40 // We save the current line width (absolute value) here.
41 // This is currently used only for X11 clipping, see src/fl_rect.cxx.
42 // FIXME: this would probably better be in class Fl::
43 int fl_line_width_
= 0;
45 #ifdef __APPLE_QUARTZ__
46 float fl_quartz_line_width_
= 1.0f
;
47 static enum CGLineCap fl_quartz_line_cap_
= kCGLineCapButt
;
48 static enum CGLineJoin fl_quartz_line_join_
= kCGLineJoinMiter
;
49 static CGFloat
*fl_quartz_line_pattern
= 0;
50 static int fl_quartz_line_pattern_size
= 0;
51 void fl_quartz_restore_line_style_() {
52 CGContextSetLineWidth(fl_gc
, fl_quartz_line_width_
);
53 CGContextSetLineCap(fl_gc
, fl_quartz_line_cap_
);
54 CGContextSetLineJoin(fl_gc
, fl_quartz_line_join_
);
55 CGContextSetLineDash(fl_gc
, 0, fl_quartz_line_pattern
, fl_quartz_line_pattern_size
);
59 void Fl_Graphics_Driver::line_style(int style
, int width
, char* dashes
) {
61 // save line width in global variable for X11 clipping
62 if (width
== 0) fl_line_width_
= 1;
63 else fl_line_width_
= width
>0 ? width
: -width
;
66 int ndashes
= dashes
? strlen(dashes
) : 0;
67 // emulate the WIN32 dash patterns on X
69 if (!ndashes
&& (style
&0xff)) {
70 int w
= width
? width
: 1;
72 // adjust lengths to account for cap:
75 dot
= 1; // unfortunately 0 does not work
81 char* p
= dashes
= buf
;
82 switch (style
& 0xff) {
83 case FL_DASH
: *p
++ = dash
; *p
++ = gap
; break;
84 case FL_DOT
: *p
++ = dot
; *p
++ = gap
; break;
85 case FL_DASHDOT
: *p
++ = dash
; *p
++ = gap
; *p
++ = dot
; *p
++ = gap
; break;
86 case FL_DASHDOTDOT
: *p
++ = dash
; *p
++ = gap
; *p
++ = dot
; *p
++ = gap
; *p
++ = dot
; *p
++ = gap
; break;
90 static int Cap
[4] = {CapButt
, CapButt
, CapRound
, CapProjecting
};
91 static int Join
[4] = {JoinMiter
, JoinMiter
, JoinRound
, JoinBevel
};
92 XSetLineAttributes(fl_display
, fl_gc
, width
,
93 ndashes
? LineOnOffDash
: LineSolid
,
94 Cap
[(style
>>8)&3], Join
[(style
>>12)&3]);
95 if (ndashes
) XSetDashes(fl_display
, fl_gc
, 0, dashes
, ndashes
);
97 // According to Bill, the "default" cap and join should be the
98 // "fastest" mode supported for the platform. I don't know why
99 // they should be different (same graphics cards, etc., right?) MRS
100 static DWORD Cap
[4]= {PS_ENDCAP_FLAT
, PS_ENDCAP_FLAT
, PS_ENDCAP_ROUND
, PS_ENDCAP_SQUARE
};
101 static DWORD Join
[4]={PS_JOIN_ROUND
, PS_JOIN_MITER
, PS_JOIN_ROUND
, PS_JOIN_BEVEL
};
102 int s1
= PS_GEOMETRIC
| Cap
[(style
>>8)&3] | Join
[(style
>>12)&3];
103 DWORD a
[16]; int n
= 0;
104 if (dashes
&& dashes
[0]) {
106 for (n
= 0; n
< 16 && *dashes
; n
++) a
[n
] = *dashes
++;
108 s1
|= style
& 0xff; // allow them to pass any low 8 bits for style
110 if ((style
|| n
) && !width
) width
= 1; // fix cards that do nothing for 0?
111 LOGBRUSH penbrush
= {BS_SOLID
,fl_RGB(),0}; // can this be fl_brush()?
112 HPEN newpen
= ExtCreatePen(s1
, width
, &penbrush
, n
, n
? a
: 0);
114 Fl::error("fl_line_style(): Could not create GDI pen object.");
117 HPEN oldpen
= (HPEN
)SelectObject(fl_gc
, newpen
);
118 DeleteObject(oldpen
);
119 DeleteObject(fl_current_xmap
->pen
);
120 fl_current_xmap
->pen
= newpen
;
121 #elif defined(__APPLE_QUARTZ__)
122 static enum CGLineCap Cap
[4] = { kCGLineCapButt
, kCGLineCapButt
,
123 kCGLineCapRound
, kCGLineCapSquare
};
124 static enum CGLineJoin Join
[4] = { kCGLineJoinMiter
, kCGLineJoinMiter
,
125 kCGLineJoinRound
, kCGLineJoinBevel
};
126 if (width
<1) width
= 1;
127 fl_quartz_line_width_
= (float)width
;
128 fl_quartz_line_cap_
= Cap
[(style
>>8)&3];
129 // when printing kCGLineCapSquare seems better for solid lines
130 if ( Fl_Surface_Device::surface()->class_name() == Fl_Printer::class_id
&& style
== FL_SOLID
&& dashes
== NULL
) {
131 fl_quartz_line_cap_
= kCGLineCapSquare
;
133 fl_quartz_line_join_
= Join
[(style
>>12)&3];
135 static CGFloat pattern
[16];
137 CGFloat
*p
= pattern
;
138 while (*d
) { *p
++ = (float)*d
++; }
139 fl_quartz_line_pattern
= pattern
;
140 fl_quartz_line_pattern_size
= d
-dashes
;
141 } else if (style
& 0xff) {
143 // adjust lengths to account for cap:
145 dash
= char(2*width
);
147 gap
= char(2*width
-1);
149 dash
= char(3*width
);
150 dot
= gap
= char(width
);
152 CGFloat
*p
= pattern
;
153 switch (style
& 0xff) {
154 case FL_DASH
: *p
++ = dash
; *p
++ = gap
; break;
155 case FL_DOT
: *p
++ = dot
; *p
++ = gap
; break;
156 case FL_DASHDOT
: *p
++ = dash
; *p
++ = gap
; *p
++ = dot
; *p
++ = gap
; break;
157 case FL_DASHDOTDOT
: *p
++ = dash
; *p
++ = gap
; *p
++ = dot
; *p
++ = gap
; *p
++ = dot
; *p
++ = gap
; break;
159 fl_quartz_line_pattern_size
= p
-pattern
;
160 fl_quartz_line_pattern
= pattern
;
162 fl_quartz_line_pattern
= 0;
163 fl_quartz_line_pattern_size
= 0;
165 fl_quartz_restore_line_style_();
167 # error unsupported platform
173 // End of "$Id: fl_line_style.cxx 8190 2011-01-05 10:21:45Z manolo $".