]> git.saurik.com Git - wxWidgets.git/blob - src/generic/textmeasure.cpp
Factor out text measurement from wxDC and wxWindow into wxTextMeasure.
[wxWidgets.git] / src / generic / textmeasure.cpp
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: src/generic/textmeasure.cpp
3 // Purpose:
4 // Author: Vadim Zeitlin
5 // Created: 2012-10-17
6 // RCS-ID: $Id$
7 // Copyright: (c) 2012 Vadim Zeitlin <vadim@wxwidgets.org>
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 #ifdef __BORLANDC__
23 #pragma hdrstop
24 #endif
25
26 #include "wx/private/textmeasure.h"
27
28 #if wxUSE_GENERIC_TEXTMEASURE
29
30 // ============================================================================
31 // wxTextMeasure generic implementation
32 // ============================================================================
33
34 // We assume that the ports not providing platform-specific wxTextMeasure
35 // implementation implement the corresponding functions in their wxDC and
36 // wxWindow classes, so forward back to them instead of using wxTextMeasure
37 // from there, as usual.
38 void wxTextMeasure::DoGetTextExtent(const wxString& string,
39 wxCoord *width,
40 wxCoord *height,
41 wxCoord *descent,
42 wxCoord *externalLeading)
43 {
44 if ( m_dc )
45 {
46 m_dc->GetTextExtent(string, width, height,
47 descent, externalLeading, m_font);
48 }
49 else if ( m_win )
50 {
51 m_win->GetTextExtent(string, width, height,
52 descent, externalLeading, m_font);
53 }
54 //else: we already asserted in the ctor, don't do it any more
55 }
56
57 // Each element of the widths array will be the width of the string up to and
58 // including the corresponding character in text. This is the generic
59 // implementation, the port-specific classes should do this with native APIs
60 // if available and if faster. Note: pango_layout_index_to_pos is much slower
61 // than calling GetTextExtent!!
62
63 #define FWC_SIZE 256
64
65 class FontWidthCache
66 {
67 public:
68 FontWidthCache() : m_scaleX(1), m_widths(NULL) { }
69 ~FontWidthCache() { delete []m_widths; }
70
71 void Reset()
72 {
73 if ( !m_widths )
74 m_widths = new int[FWC_SIZE];
75
76 memset(m_widths, 0, sizeof(int)*FWC_SIZE);
77 }
78
79 wxFont m_font;
80 double m_scaleX;
81 int *m_widths;
82 };
83
84 static FontWidthCache s_fontWidthCache;
85
86 bool wxTextMeasure::DoGetPartialTextExtents(const wxString& text,
87 wxArrayInt& widths,
88 double scaleX)
89 {
90 int totalWidth = 0;
91
92 // reset the cache if font or horizontal scale have changed
93 if ( !s_fontWidthCache.m_widths ||
94 !wxIsSameDouble(s_fontWidthCache.m_scaleX, scaleX) ||
95 (s_fontWidthCache.m_font != *m_font) )
96 {
97 s_fontWidthCache.Reset();
98 s_fontWidthCache.m_font = *m_font;
99 s_fontWidthCache.m_scaleX = scaleX;
100 }
101
102 // Calculate the position of each character based on the widths of
103 // the previous characters. This is inexact for not fixed fonts.
104 int n = 0;
105 for ( wxString::const_iterator it = text.begin();
106 it != text.end();
107 ++it )
108 {
109 const wxChar c = *it;
110 unsigned int c_int = (unsigned int)c;
111
112 int w;
113 if ((c_int < FWC_SIZE) && (s_fontWidthCache.m_widths[c_int] != 0))
114 {
115 w = s_fontWidthCache.m_widths[c_int];
116 }
117 else
118 {
119 DoGetTextExtent(c, &w, NULL);
120 if (c_int < FWC_SIZE)
121 s_fontWidthCache.m_widths[c_int] = w;
122 }
123
124 totalWidth += w;
125 widths[n++] = totalWidth;
126 }
127
128 return true;
129 }
130
131 #endif // wxUSE_GENERIC_TEXTMEASURE