]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/textmeasurecmn.cpp
Factor out text measurement from wxDC and wxWindow into wxTextMeasure.
[wxWidgets.git] / src / common / textmeasurecmn.cpp
diff --git a/src/common/textmeasurecmn.cpp b/src/common/textmeasurecmn.cpp
new file mode 100644 (file)
index 0000000..bb16ac0
--- /dev/null
@@ -0,0 +1,178 @@
+///////////////////////////////////////////////////////////////////////////////
+// Name:        src/common/textmeasurecmn.cpp
+// Purpose:     wxTextMeasureBase implementation
+// Author:      Manuel Martin
+// Created:     2012-10-05
+// Copyright:   (c) 1997-2012 wxWidgets team
+// Licence:     wxWindows licence
+///////////////////////////////////////////////////////////////////////////////
+
+// ============================================================================
+// declarations
+// ============================================================================
+
+// ----------------------------------------------------------------------------
+// headers
+// ----------------------------------------------------------------------------
+
+// for compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/dc.h"
+    #include "wx/window.h"
+#endif //WX_PRECOMP
+
+#include "wx/private/textmeasure.h"
+
+// ============================================================================
+// wxTextMeasureBase implementation
+// ============================================================================
+
+wxTextMeasureBase::wxTextMeasureBase(const wxDC *dc, const wxFont *theFont)
+    : m_dc(dc),
+      m_win(NULL),
+      m_font(theFont)
+{
+    wxASSERT_MSG( dc, wxS("wxTextMeasure needs a valid wxDC") );
+}
+
+wxTextMeasureBase::wxTextMeasureBase(const wxWindow *win, const wxFont *theFont)
+    : m_dc(NULL),
+      m_win(win),
+      m_font(theFont)
+{
+    wxASSERT_MSG( win, wxS("wxTextMeasure needs a valid wxWindow") );
+}
+
+void wxTextMeasureBase::GetTextExtent(const wxString& string,
+                                      wxCoord *width,
+                                      wxCoord *height,
+                                      wxCoord *descent,
+                                      wxCoord *externalLeading)
+{
+    // To make the code simpler, make sure that the width and height pointers
+    // are always valid, even if they point to dummy variables.
+    int unusedWidth, unusedHeight;
+    if ( !width )
+        width = &unusedWidth;
+    if ( !height )
+        height = &unusedHeight;
+
+    if ( string.empty() )
+    {
+        *width =
+        *height = 0;
+
+        return;
+    }
+
+    MeasuringGuard guard(*this);
+
+    DoGetTextExtent(string, width, height, descent, externalLeading);
+}
+
+void wxTextMeasureBase::GetMultiLineTextExtent(const wxString& text,
+                                               wxCoord *width,
+                                               wxCoord *height,
+                                               wxCoord *heightOneLine)
+{
+    MeasuringGuard guard(*this);
+
+    wxCoord widthTextMax = 0, widthLine,
+            heightTextTotal = 0, heightLineDefault = 0, heightLine = 0;
+
+    wxString curLine;
+    for ( wxString::const_iterator pc = text.begin(); ; ++pc )
+    {
+        if ( pc == text.end() || *pc == wxS('\n') )
+        {
+            if ( curLine.empty() )
+            {
+                // we can't use GetTextExtent - it will return 0 for both width
+                // and height and an empty line should count in height
+                // calculation
+
+                // assume that this line has the same height as the previous
+                // one
+                if ( !heightLineDefault )
+                    heightLineDefault = heightLine;
+
+                if ( !heightLineDefault )
+                {
+                    // but we don't know it yet - choose something reasonable
+                    DoGetTextExtent(wxS("W"), NULL, &heightLineDefault);
+                }
+
+                heightTextTotal += heightLineDefault;
+            }
+            else
+            {
+                DoGetTextExtent(curLine, &widthLine, &heightLine);
+                if ( widthLine > widthTextMax )
+                    widthTextMax = widthLine;
+                heightTextTotal += heightLine;
+            }
+
+            if ( pc == text.end() )
+            {
+               break;
+            }
+            else // '\n'
+            {
+               curLine.clear();
+            }
+        }
+        else
+        {
+            curLine += *pc;
+        }
+    }
+
+    if ( width )
+        *width = widthTextMax;
+    if ( height )
+        *height = heightTextTotal;
+    if ( heightOneLine )
+        *heightOneLine = heightLine;
+}
+
+void wxTextMeasureBase::GetLargestStringExtent(const wxVector<wxString>& strings,
+                                               wxCoord *width,
+                                               wxCoord *height)
+{
+    MeasuringGuard guard(*this);
+
+    wxCoord w, h, widthMax = 0, heightMax = 0;
+    for ( wxVector<wxString>::const_iterator i = strings.begin();
+          i != strings.end();
+          ++i )
+    {
+        DoGetTextExtent(*i, &w, &h);
+
+        if ( w > widthMax )
+            widthMax = w;
+        if ( h > heightMax )
+            heightMax = h;
+    }
+
+    if ( width )
+        *width = widthMax;
+    if ( height )
+        *height = heightMax;
+}
+
+bool wxTextMeasureBase::GetPartialTextExtents(const wxString& text,
+                                              wxArrayInt& widths,
+                                              double scaleX)
+{
+    widths.Empty();
+    if ( text.empty() )
+        return true;
+
+    MeasuringGuard guard(*this);
+
+    widths.Add(0, text.length());
+
+    return DoGetPartialTextExtents(text, widths, scaleX);
+}