1 /////////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/common/textmeasurecmn.cpp 
   3 // Purpose:     wxTextMeasureBase implementation 
   4 // Author:      Manuel Martin 
   7 // Copyright:   (c) 1997-2012 wxWidgets team 
   8 // Licence:     wxWindows licence 
   9 /////////////////////////////////////////////////////////////////////////////// 
  11 // ============================================================================ 
  13 // ============================================================================ 
  15 // ---------------------------------------------------------------------------- 
  17 // ---------------------------------------------------------------------------- 
  19 // for compilers that support precompilation, includes "wx.h". 
  20 #include "wx/wxprec.h" 
  24     #include "wx/window.h" 
  27 #include "wx/private/textmeasure.h" 
  29 // ============================================================================ 
  30 // wxTextMeasureBase implementation 
  31 // ============================================================================ 
  33 wxTextMeasureBase::wxTextMeasureBase(const wxDC 
*dc
, const wxFont 
*theFont
) 
  38     wxASSERT_MSG( dc
, wxS("wxTextMeasure needs a valid wxDC") ); 
  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. 
  45 wxTextMeasureBase::wxTextMeasureBase(const wxWindow 
*win
, const wxFont 
*theFont
) 
  50     wxASSERT_MSG( win
, wxS("wxTextMeasure needs a valid wxWindow") ); 
  52     // We don't have any wxDC so we can't forward to it. 
  56 wxFont 
wxTextMeasureBase::GetFont() const 
  58     return m_font 
? *m_font
 
  59                   : m_win 
? m_win
->GetFont() 
  63 void wxTextMeasureBase::CallGetTextExtent(const wxString
& string
, 
  67                                           wxCoord 
*externalLeading
) 
  70         m_dc
->GetTextExtent(string
, width
, height
, descent
, externalLeading
); 
  72         DoGetTextExtent(string
, width
, height
, descent
, externalLeading
); 
  75 void wxTextMeasureBase::GetTextExtent(const wxString
& string
, 
  79                                       wxCoord 
*externalLeading
) 
  81     // To make the code simpler, make sure that the width and height pointers 
  82     // are always valid, even if they point to dummy variables. 
  83     int unusedWidth
, unusedHeight
; 
  87         height 
= &unusedHeight
; 
  89     // Avoid even setting up the DC for measuring if we don't actually need to 
  91     if ( string
.empty() && !descent 
&& !externalLeading 
) 
  99     MeasuringGuard 
guard(*this); 
 101     CallGetTextExtent(string
, width
, height
, descent
, externalLeading
); 
 104 void wxTextMeasureBase::GetMultiLineTextExtent(const wxString
& text
, 
 107                                                wxCoord 
*heightOneLine
) 
 109     MeasuringGuard 
guard(*this); 
 111     wxCoord widthTextMax 
= 0, widthLine
, 
 112             heightTextTotal 
= 0, heightLineDefault 
= 0, heightLine 
= 0; 
 115     for ( wxString::const_iterator pc 
= text
.begin(); ; ++pc 
) 
 117         if ( pc 
== text
.end() || *pc 
== wxS('\n') ) 
 119             if ( curLine
.empty() ) 
 121                 // we can't use GetTextExtent - it will return 0 for both width 
 122                 // and height and an empty line should count in height 
 125                 // assume that this line has the same height as the previous 
 127                 if ( !heightLineDefault 
) 
 128                     heightLineDefault 
= heightLine
; 
 130                 if ( !heightLineDefault 
) 
 132                     // but we don't know it yet - choose something reasonable 
 134                     CallGetTextExtent(wxS("W"), &dummy
, &heightLineDefault
); 
 137                 heightTextTotal 
+= heightLineDefault
; 
 141                 CallGetTextExtent(curLine
, &widthLine
, &heightLine
); 
 142                 if ( widthLine 
> widthTextMax 
) 
 143                     widthTextMax 
= widthLine
; 
 144                 heightTextTotal 
+= heightLine
; 
 147             if ( pc 
== text
.end() ) 
 163         *width 
= widthTextMax
; 
 165         *height 
= heightTextTotal
; 
 167         *heightOneLine 
= heightLine
; 
 170 wxSize 
wxTextMeasureBase::GetLargestStringExtent(size_t n
, 
 171                                                  const wxString
* strings
) 
 173     MeasuringGuard 
guard(*this); 
 175     wxCoord w
, h
, widthMax 
= 0, heightMax 
= 0; 
 176     for ( size_t i 
= 0; i 
< n
; ++i 
) 
 178         CallGetTextExtent(strings
[i
], &w
, &h
); 
 186     return wxSize(widthMax
, heightMax
); 
 189 bool wxTextMeasureBase::GetPartialTextExtents(const wxString
& text
, 
 197     MeasuringGuard 
guard(*this); 
 199     widths
.Add(0, text
.length()); 
 201     return DoGetPartialTextExtents(text
, widths
, scaleX
); 
 204 // ---------------------------------------------------------------------------- 
 205 // Generic and inefficient DoGetPartialTextExtents() implementation. 
 206 // ---------------------------------------------------------------------------- 
 208 // Each element of the widths array will be the width of the string up to and 
 209 // including the corresponding character in text.  This is the generic 
 210 // implementation, the port-specific classes should do this with native APIs 
 211 // if available and if faster.  Note: pango_layout_index_to_pos is much slower 
 212 // than calling GetTextExtent!! 
 219     FontWidthCache() : m_scaleX(1), m_widths(NULL
) { } 
 220     ~FontWidthCache() { delete []m_widths
; } 
 225             m_widths 
= new int[FWC_SIZE
]; 
 227         memset(m_widths
, 0, sizeof(int)*FWC_SIZE
); 
 235 static FontWidthCache s_fontWidthCache
; 
 237 bool wxTextMeasureBase::DoGetPartialTextExtents(const wxString
& text
, 
 243     // reset the cache if font or horizontal scale have changed 
 244     if ( !s_fontWidthCache
.m_widths 
|| 
 245          !wxIsSameDouble(s_fontWidthCache
.m_scaleX
, scaleX
) || 
 246          (s_fontWidthCache
.m_font 
!= *m_font
) ) 
 248         s_fontWidthCache
.Reset(); 
 249         s_fontWidthCache
.m_font 
= *m_font
; 
 250         s_fontWidthCache
.m_scaleX 
= scaleX
; 
 253     // Calculate the position of each character based on the widths of 
 254     // the previous characters. This is inexact for not fixed fonts. 
 256     for ( wxString::const_iterator it 
= text
.begin(); 
 260         const wxChar c 
= *it
; 
 261         unsigned int c_int 
= (unsigned int)c
; 
 264         if ((c_int 
< FWC_SIZE
) && (s_fontWidthCache
.m_widths
[c_int
] != 0)) 
 266             w 
= s_fontWidthCache
.m_widths
[c_int
]; 
 270             DoGetTextExtent(c
, &w
, NULL
); 
 271             if (c_int 
< FWC_SIZE
) 
 272                 s_fontWidthCache
.m_widths
[c_int
] = w
; 
 276         widths
[n
++] = totalWidth
;