]> git.saurik.com Git - wxWidgets.git/blob - src/common/textmeasurecmn.cpp
Allow wxTextMeasure to work with non-native wxDC objects too.
[wxWidgets.git] / src / common / textmeasurecmn.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/common/textmeasurecmn.cpp
3 // Purpose: wxTextMeasureBase implementation
4 // Author: Manuel Martin
5 // Created: 2012-10-05
6 // RCS-ID: $Id:
7 // Copyright: (c) 1997-2012 wxWidgets team
8 // Licence: wxWindows licence
9 ///////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // ----------------------------------------------------------------------------
16 // headers
17 // ----------------------------------------------------------------------------
18
19 // for compilers that support precompilation, includes "wx.h".
20 #include "wx/wxprec.h"
21
22 #ifndef WX_PRECOMP
23 #include "wx/dc.h"
24 #include "wx/window.h"
25 #endif //WX_PRECOMP
26
27 #include "wx/private/textmeasure.h"
28
29 // ============================================================================
30 // wxTextMeasureBase implementation
31 // ============================================================================
32
33 wxTextMeasureBase::wxTextMeasureBase(const wxDC *dc, const wxFont *theFont)
34 : m_dc(dc),
35 m_win(NULL),
36 m_font(theFont)
37 {
38 wxASSERT_MSG( dc, wxS("wxTextMeasure needs a valid wxDC") );
39
40 // By default, use wxDC version, we'll explicitly reset this to false in
41 // the derived classes if the DC is of native variety.
42 m_useDCImpl = true;
43 }
44
45 wxTextMeasureBase::wxTextMeasureBase(const wxWindow *win, const wxFont *theFont)
46 : m_dc(NULL),
47 m_win(win),
48 m_font(theFont)
49 {
50 wxASSERT_MSG( win, wxS("wxTextMeasure needs a valid wxWindow") );
51
52 // We don't have any wxDC so we can't forward to it.
53 m_useDCImpl = false;
54 }
55
56 void wxTextMeasureBase::CallGetTextExtent(const wxString& string,
57 wxCoord *width,
58 wxCoord *height,
59 wxCoord *descent,
60 wxCoord *externalLeading)
61 {
62 if ( m_useDCImpl )
63 m_dc->GetTextExtent(string, width, height, descent, externalLeading);
64 else
65 DoGetTextExtent(string, width, height, descent, externalLeading);
66 }
67
68 void wxTextMeasureBase::GetTextExtent(const wxString& string,
69 wxCoord *width,
70 wxCoord *height,
71 wxCoord *descent,
72 wxCoord *externalLeading)
73 {
74 // To make the code simpler, make sure that the width and height pointers
75 // are always valid, even if they point to dummy variables.
76 int unusedWidth, unusedHeight;
77 if ( !width )
78 width = &unusedWidth;
79 if ( !height )
80 height = &unusedHeight;
81
82 if ( string.empty() )
83 {
84 *width =
85 *height = 0;
86
87 return;
88 }
89
90 MeasuringGuard guard(*this);
91
92 CallGetTextExtent(string, width, height, descent, externalLeading);
93 }
94
95 void wxTextMeasureBase::GetMultiLineTextExtent(const wxString& text,
96 wxCoord *width,
97 wxCoord *height,
98 wxCoord *heightOneLine)
99 {
100 MeasuringGuard guard(*this);
101
102 wxCoord widthTextMax = 0, widthLine,
103 heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
104
105 wxString curLine;
106 for ( wxString::const_iterator pc = text.begin(); ; ++pc )
107 {
108 if ( pc == text.end() || *pc == wxS('\n') )
109 {
110 if ( curLine.empty() )
111 {
112 // we can't use GetTextExtent - it will return 0 for both width
113 // and height and an empty line should count in height
114 // calculation
115
116 // assume that this line has the same height as the previous
117 // one
118 if ( !heightLineDefault )
119 heightLineDefault = heightLine;
120
121 if ( !heightLineDefault )
122 {
123 // but we don't know it yet - choose something reasonable
124 int dummy;
125 CallGetTextExtent(wxS("W"), &dummy, &heightLineDefault);
126 }
127
128 heightTextTotal += heightLineDefault;
129 }
130 else
131 {
132 CallGetTextExtent(curLine, &widthLine, &heightLine);
133 if ( widthLine > widthTextMax )
134 widthTextMax = widthLine;
135 heightTextTotal += heightLine;
136 }
137
138 if ( pc == text.end() )
139 {
140 break;
141 }
142 else // '\n'
143 {
144 curLine.clear();
145 }
146 }
147 else
148 {
149 curLine += *pc;
150 }
151 }
152
153 if ( width )
154 *width = widthTextMax;
155 if ( height )
156 *height = heightTextTotal;
157 if ( heightOneLine )
158 *heightOneLine = heightLine;
159 }
160
161 void wxTextMeasureBase::GetLargestStringExtent(const wxVector<wxString>& strings,
162 wxCoord *width,
163 wxCoord *height)
164 {
165 MeasuringGuard guard(*this);
166
167 wxCoord w, h, widthMax = 0, heightMax = 0;
168 for ( wxVector<wxString>::const_iterator i = strings.begin();
169 i != strings.end();
170 ++i )
171 {
172 CallGetTextExtent(*i, &w, &h);
173
174 if ( w > widthMax )
175 widthMax = w;
176 if ( h > heightMax )
177 heightMax = h;
178 }
179
180 if ( width )
181 *width = widthMax;
182 if ( height )
183 *height = heightMax;
184 }
185
186 bool wxTextMeasureBase::GetPartialTextExtents(const wxString& text,
187 wxArrayInt& widths,
188 double scaleX)
189 {
190 widths.Empty();
191 if ( text.empty() )
192 return true;
193
194 MeasuringGuard guard(*this);
195
196 widths.Add(0, text.length());
197
198 return DoGetPartialTextExtents(text, widths, scaleX);
199 }