Rotated text patch from Hans-Joachim Baader (with some corrections)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@4833 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
@@ -16,12 +16,15 @@ wxBase:
|
|||||||
|
|
||||||
all (GUI):
|
all (GUI):
|
||||||
- wxMenu(Bar)::Insert() and Remove() functions for dynamic menu menagament
|
- wxMenu(Bar)::Insert() and Remove() functions for dynamic menu menagament
|
||||||
|
- wxToolBar supports arbitrary controls (not only buttons) and can be
|
||||||
|
dynamically changed (Delete/Insert functions)
|
||||||
|
- wxDC::DrawRotatedText() (contributed by Hans-Joachim Baader, limited to
|
||||||
|
+/-90 degrees for now - contributions to improve it are welcome!)
|
||||||
|
|
||||||
wxMSW:
|
wxMSW:
|
||||||
|
|
||||||
- wxTreeCtrl::IsVisible() bug fixed (thanks to Gary Chessun)
|
- wxTreeCtrl::IsVisible() bug fixed (thanks to Gary Chessun)
|
||||||
- tooltips work with wxRadioBox
|
- tooltips work with wxRadioBox
|
||||||
- arbitrary controls (and not only buttons) can be put into a toolbar
|
|
||||||
|
|
||||||
wxGTK:
|
wxGTK:
|
||||||
|
|
||||||
|
@@ -181,6 +181,11 @@ public:
|
|||||||
void DrawText(const wxString& text, const wxPoint& pt)
|
void DrawText(const wxString& text, const wxPoint& pt)
|
||||||
{ DoDrawText(text, pt.x, pt.y); }
|
{ DoDrawText(text, pt.x, pt.y); }
|
||||||
|
|
||||||
|
void DrawRotatedText(const wxString& text, wxCoord x, wxCoord y, double angle)
|
||||||
|
{ DoDrawRotatedText(text, x, y, angle); }
|
||||||
|
void DrawRotatedText(const wxString& text, const wxPoint& pt, double angle)
|
||||||
|
{ DoDrawRotatedText(text, pt.x, pt.y, angle); }
|
||||||
|
|
||||||
bool Blit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
|
bool Blit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
|
||||||
wxDC *source, wxCoord xsrc, wxCoord ysrc,
|
wxDC *source, wxCoord xsrc, wxCoord ysrc,
|
||||||
int rop = wxCOPY, bool useMask = FALSE)
|
int rop = wxCOPY, bool useMask = FALSE)
|
||||||
@@ -497,6 +502,8 @@ protected:
|
|||||||
bool useMask = FALSE) = 0;
|
bool useMask = FALSE) = 0;
|
||||||
|
|
||||||
virtual void DoDrawText(const wxString& text, wxCoord x, wxCoord y) = 0;
|
virtual void DoDrawText(const wxString& text, wxCoord x, wxCoord y) = 0;
|
||||||
|
virtual void DoDrawRotatedText(const wxString& text,
|
||||||
|
wxCoord x, wxCoord y, double angle) = 0;
|
||||||
|
|
||||||
virtual bool DoBlit(wxCoord xdest, wxCoord ydest,
|
virtual bool DoBlit(wxCoord xdest, wxCoord ydest,
|
||||||
wxCoord width, wxCoord height,
|
wxCoord width, wxCoord height,
|
||||||
|
@@ -86,6 +86,7 @@ public:
|
|||||||
void DoDrawBitmap( const wxBitmap& bitmap, wxCoord x, wxCoord y, bool useMask=FALSE );
|
void DoDrawBitmap( const wxBitmap& bitmap, wxCoord x, wxCoord y, bool useMask=FALSE );
|
||||||
|
|
||||||
void DoDrawText(const wxString& text, wxCoord x, wxCoord y );
|
void DoDrawText(const wxString& text, wxCoord x, wxCoord y );
|
||||||
|
void DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y, double angle);
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
void SetFont( const wxFont& font );
|
void SetFont( const wxFont& font );
|
||||||
|
@@ -70,6 +70,8 @@ public:
|
|||||||
int logical_func = wxCOPY, bool useMask = FALSE );
|
int logical_func = wxCOPY, bool useMask = FALSE );
|
||||||
|
|
||||||
virtual void DoDrawText( const wxString &text, wxCoord x, wxCoord y );
|
virtual void DoDrawText( const wxString &text, wxCoord x, wxCoord y );
|
||||||
|
virtual void DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y,
|
||||||
|
double angle);
|
||||||
virtual void DoGetTextExtent( const wxString &string,
|
virtual void DoGetTextExtent( const wxString &string,
|
||||||
wxCoord *width, wxCoord *height,
|
wxCoord *width, wxCoord *height,
|
||||||
wxCoord *descent = (wxCoord *) NULL,
|
wxCoord *descent = (wxCoord *) NULL,
|
||||||
|
@@ -70,6 +70,8 @@ public:
|
|||||||
int logical_func = wxCOPY, bool useMask = FALSE );
|
int logical_func = wxCOPY, bool useMask = FALSE );
|
||||||
|
|
||||||
virtual void DoDrawText( const wxString &text, wxCoord x, wxCoord y );
|
virtual void DoDrawText( const wxString &text, wxCoord x, wxCoord y );
|
||||||
|
virtual void DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y,
|
||||||
|
double angle);
|
||||||
virtual void DoGetTextExtent( const wxString &string,
|
virtual void DoGetTextExtent( const wxString &string,
|
||||||
wxCoord *width, wxCoord *height,
|
wxCoord *width, wxCoord *height,
|
||||||
wxCoord *descent = (wxCoord *) NULL,
|
wxCoord *descent = (wxCoord *) NULL,
|
||||||
|
@@ -113,6 +113,7 @@ protected:
|
|||||||
virtual void DoCrossHair(wxCoord x, wxCoord y);
|
virtual void DoCrossHair(wxCoord x, wxCoord y);
|
||||||
|
|
||||||
virtual void DoDrawText(const wxString& text, wxCoord x, wxCoord y);
|
virtual void DoDrawText(const wxString& text, wxCoord x, wxCoord y);
|
||||||
|
virtual void DoDrawRotatedText(const wxString &text, long x, long y, double angle);
|
||||||
|
|
||||||
virtual bool DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
|
virtual bool DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
|
||||||
wxDC *source, wxCoord xsrc, wxCoord ysrc,
|
wxDC *source, wxCoord xsrc, wxCoord ysrc,
|
||||||
|
@@ -166,6 +166,8 @@ protected:
|
|||||||
bool useMask = FALSE);
|
bool useMask = FALSE);
|
||||||
|
|
||||||
virtual void DoDrawText(const wxString& text, wxCoord x, wxCoord y);
|
virtual void DoDrawText(const wxString& text, wxCoord x, wxCoord y);
|
||||||
|
virtual void DoDrawRotatedText(const wxString& text, wxCoord x, wxCoord y,
|
||||||
|
double angle);
|
||||||
|
|
||||||
virtual bool DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
|
virtual bool DoBlit(wxCoord xdest, wxCoord ydest, wxCoord width, wxCoord height,
|
||||||
wxDC *source, wxCoord xsrc, wxCoord ysrc,
|
wxDC *source, wxCoord xsrc, wxCoord ysrc,
|
||||||
|
@@ -278,6 +278,9 @@ void MyCanvas::OnPaint(wxPaintEvent &WXUNUSED(event))
|
|||||||
|
|
||||||
dc.DrawText( "This is text", 110, 10 );
|
dc.DrawText( "This is text", 110, 10 );
|
||||||
|
|
||||||
|
dc.DrawRotatedText( "+90 rotated text", 30, 30, 90 );
|
||||||
|
dc.DrawRotatedText( "-90 rotated text", 30, 30, -90 );
|
||||||
|
|
||||||
dc.SetFont( wxFont( 18, wxSWISS, wxNORMAL, wxNORMAL ) );
|
dc.SetFont( wxFont( 18, wxSWISS, wxNORMAL, wxNORMAL ) );
|
||||||
|
|
||||||
dc.DrawText( "This is Swiss 18pt text.", 110, 40 );
|
dc.DrawText( "This is Swiss 18pt text.", 110, 40 );
|
||||||
|
@@ -780,10 +780,10 @@ void wxPrintPreviewBase::SetZoom(int percent)
|
|||||||
m_previewBitmap = NULL;
|
m_previewBitmap = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (m_previewCanvas)
|
if (m_previewCanvas)
|
||||||
{
|
{
|
||||||
RenderPage(m_currentPage);
|
RenderPage(m_currentPage);
|
||||||
|
((wxScrolledWindow *) m_previewCanvas)->Scroll(0, 0);
|
||||||
m_previewCanvas->Clear();
|
m_previewCanvas->Clear();
|
||||||
m_previewCanvas->Refresh();
|
m_previewCanvas->Refresh();
|
||||||
}
|
}
|
||||||
|
@@ -1240,6 +1240,116 @@ void wxPostScriptDC::DoDrawText( const wxString& text, wxCoord x, wxCoord y )
|
|||||||
CalcBoundingBox( x + size * text.Length() * 2/3 , y );
|
CalcBoundingBox( x + size * text.Length() * 2/3 , y );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxPostScriptDC::DoDrawRotatedText( const wxString& text, wxCoord x, wxCoord y, double angle )
|
||||||
|
{
|
||||||
|
if (angle == 0.0)
|
||||||
|
{
|
||||||
|
DoDrawText(text, x, y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxCHECK_RET( m_ok && m_pstream, wxT("invalid postscript dc") );
|
||||||
|
|
||||||
|
SetFont( m_font );
|
||||||
|
|
||||||
|
if (m_textForegroundColour.Ok())
|
||||||
|
{
|
||||||
|
unsigned char red = m_textForegroundColour.Red();
|
||||||
|
unsigned char blue = m_textForegroundColour.Blue();
|
||||||
|
unsigned char green = m_textForegroundColour.Green();
|
||||||
|
|
||||||
|
if (!m_colour)
|
||||||
|
{
|
||||||
|
// Anything not white is black
|
||||||
|
if (! (red == (unsigned char) 255 &&
|
||||||
|
blue == (unsigned char) 255 &&
|
||||||
|
green == (unsigned char) 255))
|
||||||
|
{
|
||||||
|
red = (unsigned char) 0;
|
||||||
|
green = (unsigned char) 0;
|
||||||
|
blue = (unsigned char) 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// maybe setgray here ?
|
||||||
|
if (!(red == m_currentRed && green == m_currentGreen && blue == m_currentBlue))
|
||||||
|
{
|
||||||
|
double redPS = (double)(red) / 255.0;
|
||||||
|
double bluePS = (double)(blue) / 255.0;
|
||||||
|
double greenPS = (double)(green) / 255.0;
|
||||||
|
|
||||||
|
fprintf( m_pstream,
|
||||||
|
"%.8f %.8f %.8f setrgbcolor\n",
|
||||||
|
redPS, greenPS, bluePS );
|
||||||
|
|
||||||
|
m_currentRed = red;
|
||||||
|
m_currentBlue = blue;
|
||||||
|
m_currentGreen = green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = m_font.GetPointSize();
|
||||||
|
|
||||||
|
long by = y + (long)floor( double(size) * 2.0 / 3.0 ); // approximate baseline
|
||||||
|
|
||||||
|
// XXX only correct for 90 degrees
|
||||||
|
fprintf( m_pstream, "%ld %ld moveto\n", XLOG2DEV(x + size), YLOG2DEV(by) );
|
||||||
|
fprintf(m_pstream, "%.8f rotate\n", angle);
|
||||||
|
|
||||||
|
/* I don't know how to write char to a stream, so I use a mini string */
|
||||||
|
char tmpbuf[2];
|
||||||
|
tmpbuf[1] = 0;
|
||||||
|
|
||||||
|
fprintf( m_pstream, "(" );
|
||||||
|
const wxWX2MBbuf textbuf = text.mb_str();
|
||||||
|
int len = strlen(textbuf);
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
{
|
||||||
|
int c = (unsigned char) textbuf[i];
|
||||||
|
if (c == ')' || c == '(' || c == '\\')
|
||||||
|
{
|
||||||
|
/* Cope with special characters */
|
||||||
|
fprintf( m_pstream, "\\" );
|
||||||
|
tmpbuf[0] = (char) c;
|
||||||
|
fprintf( m_pstream, tmpbuf );
|
||||||
|
}
|
||||||
|
else if ( c >= 128 )
|
||||||
|
{
|
||||||
|
/* Cope with character codes > 127 */
|
||||||
|
fprintf(m_pstream, "\\%o", c);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tmpbuf[0] = (char) c;
|
||||||
|
fprintf( m_pstream, tmpbuf );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf( m_pstream, ") show\n" );
|
||||||
|
fprintf( m_pstream, "%.8f rotate\n", -angle );
|
||||||
|
|
||||||
|
if (m_font.GetUnderlined())
|
||||||
|
{
|
||||||
|
long uy = (long)(y + size - m_underlinePosition);
|
||||||
|
long w, h;
|
||||||
|
GetTextExtent(text, &w, &h);
|
||||||
|
|
||||||
|
fprintf( m_pstream,
|
||||||
|
"gsave\n"
|
||||||
|
"%ld %ld moveto\n"
|
||||||
|
"%ld setlinewidth\n"
|
||||||
|
"%ld %ld lineto\n"
|
||||||
|
"stroke\n"
|
||||||
|
"grestore\n",
|
||||||
|
XLOG2DEV(x), YLOG2DEV(uy),
|
||||||
|
(long)m_underlineThickness,
|
||||||
|
XLOG2DEV(x + w), YLOG2DEV(uy) );
|
||||||
|
}
|
||||||
|
|
||||||
|
CalcBoundingBox( x, y );
|
||||||
|
CalcBoundingBox( x + size * text.Length() * 2/3 , y );
|
||||||
|
}
|
||||||
|
|
||||||
void wxPostScriptDC::SetBackground (const wxBrush& brush)
|
void wxPostScriptDC::SetBackground (const wxBrush& brush)
|
||||||
{
|
{
|
||||||
|
@@ -39,7 +39,7 @@ static GdkPixmap **hatch_bitmap = (GdkPixmap **) NULL;
|
|||||||
// constants
|
// constants
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define RAD2DEG 57.2957795131
|
const double RAD2DEG = 180.0 / M_PI;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// temporary implementation of the missing GDK function
|
// temporary implementation of the missing GDK function
|
||||||
@@ -85,6 +85,25 @@ void gdk_draw_bitmap (GdkDrawable *drawable,
|
|||||||
1 );
|
1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compare two doubles and return the larger rounded
|
||||||
|
* to the nearest int
|
||||||
|
*/
|
||||||
|
static int roundmax(double a, double b)
|
||||||
|
{
|
||||||
|
return (int)((a > b ? a : b) + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compare two doubles and return the smaller rounded
|
||||||
|
* to the nearest int
|
||||||
|
*/
|
||||||
|
static int roundmin(double a, double b)
|
||||||
|
{
|
||||||
|
return (int)((a < b ? a : b) - 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// wxWindowDC
|
// wxWindowDC
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -783,18 +802,97 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
|
|||||||
properties (see wxXt implementation) */
|
properties (see wxXt implementation) */
|
||||||
if (m_font.GetUnderlined())
|
if (m_font.GetUnderlined())
|
||||||
{
|
{
|
||||||
wxCoord width = gdk_string_width( font, text.mbc_str() );
|
long width = gdk_string_width( font, text.mbc_str() );
|
||||||
wxCoord ul_y = y + font->ascent;
|
long ul_y = y + font->ascent;
|
||||||
if (font->descent > 0) ul_y++;
|
if (font->descent > 0) ul_y++;
|
||||||
gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
|
gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxCoord w, h;
|
long w, h;
|
||||||
GetTextExtent (text, &w, &h);
|
GetTextExtent (text, &w, &h);
|
||||||
CalcBoundingBox (x + w, y + h);
|
CalcBoundingBox (x + w, y + h);
|
||||||
CalcBoundingBox (x, y);
|
CalcBoundingBox (x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
|
||||||
|
{
|
||||||
|
if (angle == 0.0)
|
||||||
|
{
|
||||||
|
DrawText(text, x, y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxCHECK_RET( Ok(), wxT("invalid window dc") );
|
||||||
|
|
||||||
|
if (!m_window) return;
|
||||||
|
|
||||||
|
GdkFont *font = m_font.GetInternalFont( m_scaleY );
|
||||||
|
|
||||||
|
wxCHECK_RET( font, wxT("invalid font") );
|
||||||
|
|
||||||
|
x = XLOG2DEV(x);
|
||||||
|
y = YLOG2DEV(y);
|
||||||
|
|
||||||
|
int cx = gdk_string_width( font, text.mbc_str() );
|
||||||
|
int cy = font->ascent + font->descent;
|
||||||
|
|
||||||
|
wxBitmap src(cx, cy);
|
||||||
|
wxMemoryDC dc;
|
||||||
|
dc.SelectObject(src);
|
||||||
|
dc.SetFont(GetFont());
|
||||||
|
dc.SetBackground(*wxWHITE_BRUSH);
|
||||||
|
dc.SetBrush(*wxBLACK_BRUSH);
|
||||||
|
dc.Clear();
|
||||||
|
dc.DrawText(text, 0, 0);
|
||||||
|
dc.SetFont(wxNullFont);
|
||||||
|
|
||||||
|
// Calculate the size of the rotated bounding box.
|
||||||
|
double dx = cos(angle / 180.0 * M_PI);
|
||||||
|
double dy = sin(angle / 180.0 * M_PI);
|
||||||
|
double x4 = -cy * dy;
|
||||||
|
double y4 = cy * dx;
|
||||||
|
double x3 = cx * dx;
|
||||||
|
double y3 = cx * dy;
|
||||||
|
double x2 = x3 + x4;
|
||||||
|
double y2 = y3 + y4;
|
||||||
|
double x1 = x;
|
||||||
|
double y1 = y;
|
||||||
|
|
||||||
|
// Create image from the source bitmap after writing the text into it.
|
||||||
|
wxImage image(src);
|
||||||
|
|
||||||
|
int minx = roundmin(0, roundmin(x4, roundmin(x2, x3)));
|
||||||
|
int miny = roundmin(0, roundmin(y4, roundmin(y2, y3)));
|
||||||
|
int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3)));
|
||||||
|
int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3)));
|
||||||
|
|
||||||
|
// This rotates counterclockwise around the top left corner.
|
||||||
|
for (int rx = minx; rx < maxx; rx++)
|
||||||
|
{
|
||||||
|
for (int ry = miny; ry < maxy; ry++)
|
||||||
|
{
|
||||||
|
// transform dest coords to source coords
|
||||||
|
int sx = (int) (rx * dx + ry * dy + 0.5);
|
||||||
|
int sy = (int) (ry * dx - rx * dy + 0.5);
|
||||||
|
if (sx >= 0 && sx < cx && sy >= 0 && sy < cy)
|
||||||
|
{
|
||||||
|
// draw black pixels, ignore white ones (i.e. transparent b/g)
|
||||||
|
if (image.GetRed(sx, sy) == 0)
|
||||||
|
{
|
||||||
|
DrawPoint(x1 + maxx - rx, cy + y1 - ry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Background
|
||||||
|
//DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO call CalcBoundingBox()
|
||||||
|
}
|
||||||
|
|
||||||
void wxWindowDC::DoGetTextExtent(const wxString &string,
|
void wxWindowDC::DoGetTextExtent(const wxString &string,
|
||||||
wxCoord *width, wxCoord *height,
|
wxCoord *width, wxCoord *height,
|
||||||
wxCoord *descent, wxCoord *externalLeading,
|
wxCoord *descent, wxCoord *externalLeading,
|
||||||
|
@@ -39,7 +39,7 @@ static GdkPixmap **hatch_bitmap = (GdkPixmap **) NULL;
|
|||||||
// constants
|
// constants
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define RAD2DEG 57.2957795131
|
const double RAD2DEG = 180.0 / M_PI;
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// temporary implementation of the missing GDK function
|
// temporary implementation of the missing GDK function
|
||||||
@@ -85,6 +85,25 @@ void gdk_draw_bitmap (GdkDrawable *drawable,
|
|||||||
1 );
|
1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compare two doubles and return the larger rounded
|
||||||
|
* to the nearest int
|
||||||
|
*/
|
||||||
|
static int roundmax(double a, double b)
|
||||||
|
{
|
||||||
|
return (int)((a > b ? a : b) + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compare two doubles and return the smaller rounded
|
||||||
|
* to the nearest int
|
||||||
|
*/
|
||||||
|
static int roundmin(double a, double b)
|
||||||
|
{
|
||||||
|
return (int)((a < b ? a : b) - 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// wxWindowDC
|
// wxWindowDC
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
@@ -783,18 +802,97 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
|
|||||||
properties (see wxXt implementation) */
|
properties (see wxXt implementation) */
|
||||||
if (m_font.GetUnderlined())
|
if (m_font.GetUnderlined())
|
||||||
{
|
{
|
||||||
wxCoord width = gdk_string_width( font, text.mbc_str() );
|
long width = gdk_string_width( font, text.mbc_str() );
|
||||||
wxCoord ul_y = y + font->ascent;
|
long ul_y = y + font->ascent;
|
||||||
if (font->descent > 0) ul_y++;
|
if (font->descent > 0) ul_y++;
|
||||||
gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
|
gdk_draw_line( m_window, m_textGC, x, ul_y, x + width, ul_y);
|
||||||
}
|
}
|
||||||
|
|
||||||
wxCoord w, h;
|
long w, h;
|
||||||
GetTextExtent (text, &w, &h);
|
GetTextExtent (text, &w, &h);
|
||||||
CalcBoundingBox (x + w, y + h);
|
CalcBoundingBox (x + w, y + h);
|
||||||
CalcBoundingBox (x, y);
|
CalcBoundingBox (x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
|
||||||
|
{
|
||||||
|
if (angle == 0.0)
|
||||||
|
{
|
||||||
|
DrawText(text, x, y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxCHECK_RET( Ok(), wxT("invalid window dc") );
|
||||||
|
|
||||||
|
if (!m_window) return;
|
||||||
|
|
||||||
|
GdkFont *font = m_font.GetInternalFont( m_scaleY );
|
||||||
|
|
||||||
|
wxCHECK_RET( font, wxT("invalid font") );
|
||||||
|
|
||||||
|
x = XLOG2DEV(x);
|
||||||
|
y = YLOG2DEV(y);
|
||||||
|
|
||||||
|
int cx = gdk_string_width( font, text.mbc_str() );
|
||||||
|
int cy = font->ascent + font->descent;
|
||||||
|
|
||||||
|
wxBitmap src(cx, cy);
|
||||||
|
wxMemoryDC dc;
|
||||||
|
dc.SelectObject(src);
|
||||||
|
dc.SetFont(GetFont());
|
||||||
|
dc.SetBackground(*wxWHITE_BRUSH);
|
||||||
|
dc.SetBrush(*wxBLACK_BRUSH);
|
||||||
|
dc.Clear();
|
||||||
|
dc.DrawText(text, 0, 0);
|
||||||
|
dc.SetFont(wxNullFont);
|
||||||
|
|
||||||
|
// Calculate the size of the rotated bounding box.
|
||||||
|
double dx = cos(angle / 180.0 * M_PI);
|
||||||
|
double dy = sin(angle / 180.0 * M_PI);
|
||||||
|
double x4 = -cy * dy;
|
||||||
|
double y4 = cy * dx;
|
||||||
|
double x3 = cx * dx;
|
||||||
|
double y3 = cx * dy;
|
||||||
|
double x2 = x3 + x4;
|
||||||
|
double y2 = y3 + y4;
|
||||||
|
double x1 = x;
|
||||||
|
double y1 = y;
|
||||||
|
|
||||||
|
// Create image from the source bitmap after writing the text into it.
|
||||||
|
wxImage image(src);
|
||||||
|
|
||||||
|
int minx = roundmin(0, roundmin(x4, roundmin(x2, x3)));
|
||||||
|
int miny = roundmin(0, roundmin(y4, roundmin(y2, y3)));
|
||||||
|
int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3)));
|
||||||
|
int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3)));
|
||||||
|
|
||||||
|
// This rotates counterclockwise around the top left corner.
|
||||||
|
for (int rx = minx; rx < maxx; rx++)
|
||||||
|
{
|
||||||
|
for (int ry = miny; ry < maxy; ry++)
|
||||||
|
{
|
||||||
|
// transform dest coords to source coords
|
||||||
|
int sx = (int) (rx * dx + ry * dy + 0.5);
|
||||||
|
int sy = (int) (ry * dx - rx * dy + 0.5);
|
||||||
|
if (sx >= 0 && sx < cx && sy >= 0 && sy < cy)
|
||||||
|
{
|
||||||
|
// draw black pixels, ignore white ones (i.e. transparent b/g)
|
||||||
|
if (image.GetRed(sx, sy) == 0)
|
||||||
|
{
|
||||||
|
DrawPoint(x1 + maxx - rx, cy + y1 - ry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Background
|
||||||
|
//DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO call CalcBoundingBox()
|
||||||
|
}
|
||||||
|
|
||||||
void wxWindowDC::DoGetTextExtent(const wxString &string,
|
void wxWindowDC::DoGetTextExtent(const wxString &string,
|
||||||
wxCoord *width, wxCoord *height,
|
wxCoord *width, wxCoord *height,
|
||||||
wxCoord *descent, wxCoord *externalLeading,
|
wxCoord *descent, wxCoord *externalLeading,
|
||||||
|
@@ -75,8 +75,6 @@ static Pixmap bdiag, cdiag, fdiag, cross, horiz, verti;
|
|||||||
// constants
|
// constants
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#define RAD2DEG 57.2957795131
|
|
||||||
|
|
||||||
// Fudge factor (VZ: what??)
|
// Fudge factor (VZ: what??)
|
||||||
#define WX_GC_CF 1
|
#define WX_GC_CF 1
|
||||||
|
|
||||||
@@ -106,6 +104,25 @@ static void XCopyRemote(Display *src_display, Display *dest_display,
|
|||||||
// implementation
|
// implementation
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compare two doubles and return the larger rounded
|
||||||
|
* to the nearest int
|
||||||
|
*/
|
||||||
|
static int roundmax(double a, double b)
|
||||||
|
{
|
||||||
|
return (int)((a > b ? a : b) + 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* compare two doubles and return the smaller rounded
|
||||||
|
* to the nearest int
|
||||||
|
*/
|
||||||
|
static int roundmin(double a, double b)
|
||||||
|
{
|
||||||
|
return (int)((a < b ? a : b) - 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// wxWindowDC
|
// wxWindowDC
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@@ -1171,6 +1188,145 @@ void wxWindowDC::DoDrawText( const wxString &text, wxCoord x, wxCoord y )
|
|||||||
CalcBoundingBox (x, y);
|
CalcBoundingBox (x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxWindowDC::DoDrawRotatedText( const wxString &text, wxCoord x, wxCoord y, double angle )
|
||||||
|
{
|
||||||
|
if (angle == 0.0)
|
||||||
|
{
|
||||||
|
DrawText(text, x, y);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxCHECK_RET( Ok(), "invalid dc" );
|
||||||
|
|
||||||
|
// Since X draws from the baseline of the text, must add the text height
|
||||||
|
int cx = 0;
|
||||||
|
int cy = 0;
|
||||||
|
int ascent = 0;
|
||||||
|
int slen;
|
||||||
|
|
||||||
|
slen = strlen(text);
|
||||||
|
|
||||||
|
if (m_font.Ok())
|
||||||
|
{
|
||||||
|
// Calculate text extent.
|
||||||
|
WXFontStructPtr pFontStruct = m_font.GetFontStruct(m_userScaleY*m_logicalScaleY, m_display);
|
||||||
|
int direction, descent;
|
||||||
|
XCharStruct overall_return;
|
||||||
|
#if 0
|
||||||
|
if (use16)
|
||||||
|
(void)XTextExtents16((XFontStruct*) pFontStruct, (XChar2b *)(const char*) text, slen, &direction,
|
||||||
|
&ascent, &descent, &overall_return);
|
||||||
|
else
|
||||||
|
#endif // 0
|
||||||
|
(void)XTextExtents((XFontStruct*) pFontStruct, (char*) (const char*) text, slen, &direction,
|
||||||
|
&ascent, &descent, &overall_return);
|
||||||
|
|
||||||
|
cx = overall_return.width;
|
||||||
|
cy = ascent + descent;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxBitmap src(cx, cy);
|
||||||
|
wxMemoryDC dc;
|
||||||
|
dc.SelectObject(src);
|
||||||
|
dc.SetFont(GetFont());
|
||||||
|
dc.SetBackground(*wxWHITE_BRUSH);
|
||||||
|
dc.SetBrush(*wxBLACK_BRUSH);
|
||||||
|
dc.Clear();
|
||||||
|
dc.DrawText(text, 0, 0);
|
||||||
|
dc.SetFont(wxNullFont);
|
||||||
|
|
||||||
|
// Calculate the size of the rotated bounding box.
|
||||||
|
double dx = cos(angle / 180.0 * M_PI);
|
||||||
|
double dy = sin(angle / 180.0 * M_PI);
|
||||||
|
double x4 = -cy * dy;
|
||||||
|
double y4 = cy * dx;
|
||||||
|
double x3 = cx * dx;
|
||||||
|
double y3 = cx * dy;
|
||||||
|
double x2 = x3 + x4;
|
||||||
|
double y2 = y3 + y4;
|
||||||
|
double x1 = x;
|
||||||
|
double y1 = y;
|
||||||
|
|
||||||
|
// Create image from the source bitmap after writing the text into it.
|
||||||
|
wxImage image(src);
|
||||||
|
|
||||||
|
int minx = roundmin(0, roundmin(x4, roundmin(x2, x3)));
|
||||||
|
int miny = roundmin(0, roundmin(y4, roundmin(y2, y3)));
|
||||||
|
int maxx = roundmax(0, roundmax(x4, roundmax(x2, x3)));
|
||||||
|
int maxy = roundmax(0, roundmax(y4, roundmax(y2, y3)));
|
||||||
|
|
||||||
|
// This rotates counterclockwise around the top left corner.
|
||||||
|
for (int rx = minx; rx < maxx; rx++)
|
||||||
|
{
|
||||||
|
for (int ry = miny; ry < maxy; ry++)
|
||||||
|
{
|
||||||
|
// transform dest coords to source coords
|
||||||
|
int sx = (int) (rx * dx + ry * dy + 0.5);
|
||||||
|
int sy = (int) (ry * dx - rx * dy + 0.5);
|
||||||
|
if (sx >= 0 && sx < cx && sy >= 0 && sy < cy)
|
||||||
|
{
|
||||||
|
// draw black pixels, ignore white ones (i.e. transparent b/g)
|
||||||
|
if (image.GetRed(sx, sy) == 0)
|
||||||
|
{
|
||||||
|
{
|
||||||
|
DrawPoint(x1 + maxx - rx, cy + y1 - ry);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Background
|
||||||
|
//DrawPoint(x1 + maxx - rx, cy + y1 + maxy - ry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// First draw a rectangle representing the text background, if a text
|
||||||
|
// background is specified
|
||||||
|
if (m_textBackgroundColour.Ok () && (m_backgroundMode != wxTRANSPARENT))
|
||||||
|
{
|
||||||
|
wxColour oldPenColour = m_currentColour;
|
||||||
|
m_currentColour = m_textBackgroundColour;
|
||||||
|
bool sameColour = (oldPenColour.Ok () && m_textBackgroundColour.Ok () &&
|
||||||
|
(oldPenColour.Red () == m_textBackgroundColour.Red ()) &&
|
||||||
|
(oldPenColour.Blue () == m_textBackgroundColour.Blue ()) &&
|
||||||
|
(oldPenColour.Green () == m_textBackgroundColour.Green ()));
|
||||||
|
|
||||||
|
// This separation of the big && test required for gcc2.7/HP UX 9.02
|
||||||
|
// or pixel value can be corrupted!
|
||||||
|
sameColour = (sameColour &&
|
||||||
|
(oldPenColour.GetPixel() == m_textBackgroundColour.GetPixel()));
|
||||||
|
|
||||||
|
if (!sameColour || !GetOptimization())
|
||||||
|
{
|
||||||
|
int pixel = m_textBackgroundColour.AllocColour(m_display);
|
||||||
|
m_currentColour = m_textBackgroundColour;
|
||||||
|
|
||||||
|
// Set the GC to the required colour
|
||||||
|
if (pixel > -1)
|
||||||
|
{
|
||||||
|
XSetForeground ((Display*) m_display, (GC) m_gc, pixel);
|
||||||
|
if (m_window && m_window->GetBackingPixmap())
|
||||||
|
XSetForeground ((Display*) m_display,(GC) m_gcBacking, pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_textBackgroundColour = oldPenColour ;
|
||||||
|
|
||||||
|
XFillRectangle ((Display*) m_display, (Pixmap) m_pixmap, (GC) m_gc, XLOG2DEV (x), YLOG2DEV (y), cx, cy);
|
||||||
|
if (m_window && m_window->GetBackingPixmap())
|
||||||
|
XFillRectangle ((Display*) m_display, (Pixmap) m_window->GetBackingPixmap(),(GC) m_gcBacking,
|
||||||
|
XLOG2DEV_2 (x), YLOG2DEV_2 (y), cx, cy);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
long w, h;
|
||||||
|
// XXX use pixmap size
|
||||||
|
GetTextExtent (text, &w, &h);
|
||||||
|
CalcBoundingBox (x + w, y + h);
|
||||||
|
CalcBoundingBox (x, y);
|
||||||
|
}
|
||||||
|
|
||||||
bool wxWindowDC::CanGetTextExtent() const
|
bool wxWindowDC::CanGetTextExtent() const
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@@ -2205,7 +2361,7 @@ static void wx_spline_draw_point_array(wxDC *dc)
|
|||||||
void wxWindowDC::DoDrawSpline( wxList *points )
|
void wxWindowDC::DoDrawSpline( wxList *points )
|
||||||
{
|
{
|
||||||
wxCHECK_RET( Ok(), wxT("invalid window dc") );
|
wxCHECK_RET( Ok(), wxT("invalid window dc") );
|
||||||
|
|
||||||
wxPoint *p;
|
wxPoint *p;
|
||||||
double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
|
double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
|
||||||
double x1, y1, x2, y2;
|
double x1, y1, x2, y2;
|
||||||
|
@@ -655,6 +655,13 @@ void wxDC::DoDrawText(const wxString& text, wxCoord x, wxCoord y)
|
|||||||
CalcBoundingBox((x + w), (y + h));
|
CalcBoundingBox((x + w), (y + h));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wxDC::DoDrawRotatedText(const wxString& text,
|
||||||
|
wxCoord x, wxCoord y,
|
||||||
|
double angle)
|
||||||
|
{
|
||||||
|
wxFAIL_MSG( _T("TODO") );
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// set GDI objects
|
// set GDI objects
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
Reference in New Issue
Block a user