diff --git a/docs/changes.txt b/docs/changes.txt index 0261e42783..6a938dcf82 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -40,3 +40,4 @@ wxMSW: - Improve wxMimeTypesManager open command detection (Eric Jensen). - Make wxFILTER_INCLUDE_LIST in wxTextValidator actually usable. - Fix handling of selected images in wxBitmapButton (Artur Wieczorek). +- Support multiline strings in wxDC::DrawRotatedText() (Artur Wieczorek). diff --git a/interface/wx/dc.h b/interface/wx/dc.h index 6d72221df4..13d6350c97 100644 --- a/interface/wx/dc.h +++ b/interface/wx/dc.h @@ -542,6 +542,9 @@ public: Draws the text rotated by @a angle degrees (positive angles are counterclockwise; the full angle is 360 degrees). + Notice that, as with DrawText(), the @a text can contain multiple lines + separated by the new line (@c '\\n') characters. + @note Under Win9x only TrueType fonts can be drawn by this function. In particular, a font different from @c wxNORMAL_FONT should be used as the latter is not a TrueType font. @c wxSWISS_FONT is an diff --git a/samples/drawing/drawing.cpp b/samples/drawing/drawing.cpp index 8ce1eeec2f..75ebb807d3 100644 --- a/samples/drawing/drawing.cpp +++ b/samples/drawing/drawing.cpp @@ -827,6 +827,10 @@ void MyCanvas::DrawText(wxDC& dc) y += height; dc.DrawText("And\nmore\ntext on\nmultiple\nlines", 110, y); + y += 5*height; + + dc.SetTextForeground(*wxBLUE); + dc.DrawRotatedText("Rotated text\ncan have\nmultiple lines\nas well", 110, y, 15); } static const struct diff --git a/src/msw/dc.cpp b/src/msw/dc.cpp index 7f12076c4e..826a8e8acf 100644 --- a/src/msw/dc.cpp +++ b/src/msw/dc.cpp @@ -1444,6 +1444,11 @@ void wxMSWDCImpl::DoDrawText(const wxString& text, wxCoord x, wxCoord y) WXMICROWIN_CHECK_HDC + // prepare for drawing the text + wxTextColoursChanger textCol(GetHdc(), *this); + + wxBkModeChanger bkMode(GetHdc(), m_backgroundMode); + DrawAnyText(text, x, y); // update the bounding box @@ -1456,13 +1461,6 @@ void wxMSWDCImpl::DoDrawText(const wxString& text, wxCoord x, wxCoord y) void wxMSWDCImpl::DrawAnyText(const wxString& text, wxCoord x, wxCoord y) { - WXMICROWIN_CHECK_HDC - - // prepare for drawing the text - wxTextColoursChanger textCol(GetHdc(), *this); - - wxBkModeChanger bkMode(GetHdc(), m_backgroundMode); - if ( ::ExtTextOut(GetHdc(), XLOG2DEV(x), YLOG2DEV(y), 0, NULL, text.c_str(), text.length(), NULL) == 0 ) { @@ -1483,6 +1481,8 @@ void wxMSWDCImpl::DoDrawRotatedText(const wxString& text, if ( (angle == 0.0) && m_font.IsOk() ) { DoDrawText(text, x, y); + + // Bounding box already updated by DoDrawText(), no need to do it again. } #ifndef __WXMICROWIN__ else @@ -1501,7 +1501,7 @@ void wxMSWDCImpl::DoDrawRotatedText(const wxString& text, // GDI wants the angle in tenth of degree long angle10 = (long)(angle * 10); lf.lfEscapement = angle10; - lf. lfOrientation = angle10; + lf.lfOrientation = angle10; hfont = ::CreateFontIndirect(&lf); if ( !hfont ) @@ -1512,29 +1512,48 @@ void wxMSWDCImpl::DoDrawRotatedText(const wxString& text, { HFONT hfontOld = (HFONT)::SelectObject(GetHdc(), hfont); - DrawAnyText(text, x, y); + // Get extent of whole text. + wxCoord w, h, heightLine; + GetOwner()->GetMultiLineTextExtent(text, &w, &h, &heightLine); + + // Prepare for drawing the text + wxTextColoursChanger textCol(GetHdc(), *this); + wxBkModeChanger bkMode(GetHdc(), m_backgroundMode); + + // Compute the shift for the origin of the next line. + const double rad = DegToRad(angle); + const double dx = heightLine * sin(rad); + const double dy = heightLine * cos(rad); + + // Draw all text line by line + const wxArrayString lines = wxSplit(text, '\n', '\0'); + for ( size_t lineNum = 0; lineNum < lines.size(); lineNum++ ) + { + // Calculate origin for each line to avoid accumulation of + // rounding errors. + DrawAnyText(lines[lineNum], + x + wxRound(lineNum*dx), + y + wxRound(lineNum*dy)); + } (void)::SelectObject(GetHdc(), hfontOld); (void)::DeleteObject(hfont); + + // call the bounding box by adding all four vertices of the rectangle + // containing the text to it (simpler and probably not slower than + // determining which of them is really topmost/leftmost/...) + + // "upper left" and "upper right" + CalcBoundingBox(x, y); + CalcBoundingBox(x + wxCoord(w*cos(rad)), y - wxCoord(w*sin(rad))); + + // "bottom left" and "bottom right" + x += (wxCoord)(h*sin(rad)); + y += (wxCoord)(h*cos(rad)); + CalcBoundingBox(x, y); + CalcBoundingBox(x + wxCoord(w*cos(rad)), y - wxCoord(w*sin(rad))); } - // call the bounding box by adding all four vertices of the rectangle - // containing the text to it (simpler and probably not slower than - // determining which of them is really topmost/leftmost/...) - wxCoord w, h; - GetOwner()->GetTextExtent(text, &w, &h); - - double rad = DegToRad(angle); - - // "upper left" and "upper right" - CalcBoundingBox(x, y); - CalcBoundingBox(x + wxCoord(w*cos(rad)), y - wxCoord(w*sin(rad))); - - // "bottom left" and "bottom right" - x += (wxCoord)(h*sin(rad)); - y += (wxCoord)(h*cos(rad)); - CalcBoundingBox(x, y); - CalcBoundingBox(x + wxCoord(w*cos(rad)), y - wxCoord(w*sin(rad))); } #endif }