X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/22c956d8a69985fa968404377c09d0d98e07a2b3..1003169e2107a98807ed8279eeb8df7e4e90ca98:/src/html/htmlcell.cpp diff --git a/src/html/htmlcell.cpp b/src/html/htmlcell.cpp index 37514300b3..114097e2fa 100644 --- a/src/html/htmlcell.cpp +++ b/src/html/htmlcell.cpp @@ -7,10 +7,6 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) -#pragma implementation "htmlcell.h" -#endif - #include "wx/wxprec.h" #include "wx/defs.h" @@ -94,6 +90,8 @@ wxHtmlCell::wxHtmlCell() : wxObject() m_Next = NULL; m_Parent = NULL; m_Width = m_Height = m_Descent = 0; + m_ScriptMode = wxHTML_SCRIPT_NORMAL; // or mode + m_ScriptBaseline = 0; // or baseline m_CanLiveOnPagebreak = true; m_Link = NULL; } @@ -103,6 +101,21 @@ wxHtmlCell::~wxHtmlCell() delete m_Link; } +// Update the descent value when whe are in a or . +// prevbase is the parent base +void wxHtmlCell::SetScriptMode(wxHtmlScriptMode mode, long previousBase) +{ + m_ScriptMode = mode; + + if (mode == wxHTML_SCRIPT_SUP) + m_ScriptBaseline = previousBase - (m_Height + 1) / 2; + else if (mode == wxHTML_SCRIPT_SUB) + m_ScriptBaseline = previousBase + (m_Height + 1) / 6; + else + m_ScriptBaseline = 0; + + m_Descent += m_ScriptBaseline; +} void wxHtmlCell::OnMouseClick(wxWindow *parent, int x, int y, const wxMouseEvent& event) @@ -256,7 +269,7 @@ bool wxHtmlCell::IsBefore(wxHtmlCell *cell) const IMPLEMENT_ABSTRACT_CLASS(wxHtmlWordCell, wxHtmlCell) -wxHtmlWordCell::wxHtmlWordCell(const wxString& word, wxDC& dc) : wxHtmlCell() +wxHtmlWordCell::wxHtmlWordCell(const wxString& word, const wxDC& dc) : wxHtmlCell() { m_Word = word; dc.GetTextExtent(m_Word, &m_Width, &m_Height, &m_Descent); @@ -276,16 +289,15 @@ void wxHtmlWordCell::SetPreviousWord(wxHtmlWordCell *cell) // Splits m_Word into up to three parts according to selection, returns // substring before, in and after selection and the points (in relative coords) // where s2 and s3 start: -void wxHtmlWordCell::Split(wxDC& dc, +void wxHtmlWordCell::Split(const wxDC& dc, const wxPoint& selFrom, const wxPoint& selTo, unsigned& pos1, unsigned& pos2) const { wxPoint pt1 = (selFrom == wxDefaultPosition) ? wxDefaultPosition : selFrom - GetAbsPos(); wxPoint pt2 = (selTo == wxDefaultPosition) ? - wxPoint(m_Width, wxDefaultPosition.y) : selTo - GetAbsPos(); + wxPoint(m_Width, wxDefaultCoord) : selTo - GetAbsPos(); - wxCoord charW, charH; unsigned len = m_Word.length(); unsigned i = 0; pos1 = 0; @@ -298,6 +310,14 @@ void wxHtmlWordCell::Split(wxDC& dc, pt2.x = m_Width; // before selection: +#ifdef __WXMAC__ + // implementation using PartialExtents to support fractional widths + wxArrayInt widths ; + dc.GetPartialTextExtents(m_Word,widths) ; + while( i < len && pt1.x >= widths[i] ) + i++ ; +#else // __WXMAC__ + wxCoord charW, charH; while ( pt1.x > 0 && i < len ) { dc.GetTextExtent(m_Word[i], &charW, &charH); @@ -308,9 +328,14 @@ void wxHtmlWordCell::Split(wxDC& dc, i++; } } +#endif // __WXMAC__/!__WXMAC__ // in selection: unsigned j = i; +#ifdef __WXMAC__ + while( j < len && pt2.x >= widths[j] ) + j++ ; +#else // __WXMAC__ pos2 = pos1; pt2.x -= pos2; while ( pt2.x > 0 && j < len ) @@ -323,12 +348,13 @@ void wxHtmlWordCell::Split(wxDC& dc, j++; } } +#endif // __WXMAC__/!__WXMAC__ pos1 = i; pos2 = j; } -void wxHtmlWordCell::SetSelectionPrivPos(wxDC& dc, wxHtmlSelection *s) const +void wxHtmlWordCell::SetSelectionPrivPos(const wxDC& dc, wxHtmlSelection *s) const { unsigned p1, p2; @@ -385,7 +411,7 @@ void wxHtmlWordCell::Draw(wxDC& dc, int x, int y, #endif bool drawSelectionAfterCell = false; - + if ( info.GetState().GetSelectionState() == wxHTML_SEL_CHANGING ) { // Selection changing, we must draw the word piecewise: @@ -637,8 +663,6 @@ void wxHtmlContainerCell::Layout(int w) return; } - wxHtmlCell *cell = m_Cells, - *line = m_Cells; wxHtmlCell *nextCell; long xpos = 0, ypos = m_IndentTop; int xdelta = 0, ybasicpos = 0, ydiff; @@ -685,6 +709,8 @@ void wxHtmlContainerCell::Layout(int w) s_width = m_Width - s_indent - ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight); // my own layouting: + wxHtmlCell *cell = m_Cells, + *line = m_Cells; while (cell != NULL) { switch (m_AlignVer) @@ -716,7 +742,7 @@ void wxHtmlContainerCell::Layout(int w) curLineWidth += cell->GetMaxTotalWidth(); cell = cell->GetNext(); - + // compute length of the next word that would be added: nextWordWidth = 0; if (cell) @@ -728,9 +754,9 @@ void wxHtmlContainerCell::Layout(int w) nextCell = nextCell->GetNext(); } while (nextCell && !nextCell->IsLinebreakAllowed()); } - - // force new line if occured: - if ((cell == NULL) || + + // force new line if occurred: + if ((cell == NULL) || (xpos + nextWordWidth > s_width && cell->IsLinebreakAllowed())) { if (xpos > MaxLineWidth) MaxLineWidth = xpos; @@ -775,51 +801,54 @@ void wxHtmlContainerCell::Layout(int w) // between two cells separated by, e.g. font change, cell which // is wrong - const int step = s_width - xpos; + int step = s_width - xpos; if ( step > 0 ) { // first count the cells which will get extra space int total = 0; - const wxHtmlCell *c, - *prev = NULL, - *next = NULL; - for ( c = line; c != cell; prev = c, c = next ) + const wxHtmlCell *c; + if ( line != cell ) { - next = c->GetNext(); - if ( c->IsLinebreakAllowed() && - (next == cell || next->IsLinebreakAllowed()) && - (!prev || prev->IsLinebreakAllowed()) ) + for ( c = line->GetNext(); c != cell; c = c->GetNext() ) { - total++; + if ( c->IsLinebreakAllowed() ) + { + total++; + } } } // and now extra space to those cells which merit it if ( total ) { - prev = - next = NULL; - for ( int n = 0; line != cell; prev = line, line = line->GetNext() ) - { - line->SetPos(line->GetPosX() + s_indent + - ((n * step) / total), - line->GetPosY() + ypos); + // first cell on line is not moved: + line->SetPos(line->GetPosX() + s_indent, + line->GetPosY() + ypos); - next = line->GetNext(); - if ( line->IsLinebreakAllowed() && - (next == cell || - next->IsLinebreakAllowed()) && - (!prev || prev->IsLinebreakAllowed()) ) + line = line->GetNext(); + for ( int n = 0; line != cell; line = line->GetNext() ) + { + if ( line->IsLinebreakAllowed() ) { // offset the next cell relative to this one // thus increasing our size n++; } + + line->SetPos(line->GetPosX() + s_indent + + ((n * step) / total), + line->GetPosY() + ypos); } } + else + { + // this will cause the code to enter "else branch" below: + step = 0; + } } - else // no extra space to distribute + // else branch: + if ( step <= 0 ) // no extra space to distribute { // just set the indent properly while (line != cell) @@ -859,7 +888,7 @@ void wxHtmlContainerCell::Layout(int w) if (curLineWidth > m_MaxTotalWidth) m_MaxTotalWidth = curLineWidth; - + m_MaxTotalWidth += s_indent + ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight); MaxLineWidth += s_indent + ((m_IndentRight < 0) ? (-m_IndentRight * m_Width / 100) : m_IndentRight); if (m_Width < MaxLineWidth) m_Width = MaxLineWidth; @@ -899,52 +928,60 @@ void wxHtmlContainerCell::Draw(wxDC& dc, int x, int y, int view_y1, int view_y2, dc.SetPen(*wxRED_PEN); dc.DrawRectangle(x+m_PosX,y+m_PosY,m_Width,m_Height); #endif - // container visible, draw it: - if ((y + m_PosY <= view_y2) && (y + m_PosY + m_Height > view_y1)) + + int xlocal = x + m_PosX; + int ylocal = y + m_PosY; + + if (m_UseBkColour) { - if (m_UseBkColour) - { - wxBrush myb = wxBrush(m_BkColour, wxSOLID); + wxBrush myb = wxBrush(m_BkColour, wxSOLID); - int real_y1 = mMax(y + m_PosY, view_y1); - int real_y2 = mMin(y + m_PosY + m_Height - 1, view_y2); + int real_y1 = mMax(ylocal, view_y1); + int real_y2 = mMin(ylocal + m_Height - 1, view_y2); - dc.SetBrush(myb); - dc.SetPen(*wxTRANSPARENT_PEN); - dc.DrawRectangle(x + m_PosX, real_y1, m_Width, real_y2 - real_y1 + 1); - } + dc.SetBrush(myb); + dc.SetPen(*wxTRANSPARENT_PEN); + dc.DrawRectangle(xlocal, real_y1, m_Width, real_y2 - real_y1 + 1); + } - if (m_UseBorder) - { - wxPen mypen1(m_BorderColour1, 1, wxSOLID); - wxPen mypen2(m_BorderColour2, 1, wxSOLID); - - dc.SetPen(mypen1); - dc.DrawLine(x + m_PosX, y + m_PosY, x + m_PosX, y + m_PosY + m_Height - 1); - dc.DrawLine(x + m_PosX, y + m_PosY, x + m_PosX + m_Width, y + m_PosY); - dc.SetPen(mypen2); - dc.DrawLine(x + m_PosX + m_Width - 1, y + m_PosY, x + m_PosX + m_Width - 1, y + m_PosY + m_Height - 1); - dc.DrawLine(x + m_PosX, y + m_PosY + m_Height - 1, x + m_PosX + m_Width, y + m_PosY + m_Height - 1); - } + if (m_UseBorder) + { + wxPen mypen1(m_BorderColour1, 1, wxSOLID); + wxPen mypen2(m_BorderColour2, 1, wxSOLID); + + dc.SetPen(mypen1); + dc.DrawLine(xlocal, ylocal, xlocal, ylocal + m_Height - 1); + dc.DrawLine(xlocal, ylocal, xlocal + m_Width, ylocal); + dc.SetPen(mypen2); + dc.DrawLine(xlocal + m_Width - 1, ylocal, xlocal + m_Width - 1, ylocal + m_Height - 1); + dc.DrawLine(xlocal, ylocal + m_Height - 1, xlocal + m_Width, ylocal + m_Height - 1); + } - if (m_Cells) + if (m_Cells) + { + // draw container's contents: + for (wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext()) { - // draw container's contents: - for (wxHtmlCell *cell = m_Cells; cell; cell = cell->GetNext()) + + // optimize drawing: don't render off-screen content: + if ((ylocal + cell->GetPosY() <= view_y2) && + (ylocal + cell->GetPosY() + cell->GetHeight() > view_y1)) { + // the cell is visible, draw it: UpdateRenderingStatePre(info, cell); cell->Draw(dc, - x + m_PosX, y + m_PosY, view_y1, view_y2, + xlocal, ylocal, view_y1, view_y2, info); UpdateRenderingStatePost(info, cell); } + else + { + // the cell is off-screen, proceed with font+color+etc. + // changes only: + cell->DrawInvisible(dc, xlocal, ylocal, info); + } } } - // container invisible, just proceed font+color changing: - else - { - DrawInvisible(dc, x, y, info); - } } @@ -1083,10 +1120,10 @@ wxHtmlCell *wxHtmlContainerCell::FindCellByPos(wxCoord x, wxCoord y, if ( cell->IsFormattingCell() ) continue; int cellY = cell->GetPosY(); - if (!( y < cellY || (y < cellY + cell->GetHeight() && + if (!( y < cellY || (y < cellY + cell->GetHeight() && x < cell->GetPosX() + cell->GetWidth()) )) continue; - + c = cell->FindCellByPos(x - cell->GetPosX(), y - cellY, flags); if (c) return c; } @@ -1172,7 +1209,7 @@ static bool IsEmptyContainer(wxHtmlContainerCell *cell) } void wxHtmlContainerCell::RemoveExtraSpacing(bool top, bool bottom) -{ +{ if ( top ) SetIndent(0, wxHTML_INDENT_TOP); if ( bottom ) @@ -1206,13 +1243,13 @@ void wxHtmlContainerCell::RemoveExtraSpacing(bool top, bool bottom) } } } - + if ( bottom ) { wxArrayPtrVoid arr; for ( c = m_Cells; c; c = c->GetNext() ) arr.Add((void*)c); - + for ( int i = arr.GetCount() - 1; i >= 0; i--) { c = (wxHtmlCell*)arr[i]; @@ -1226,7 +1263,8 @@ void wxHtmlContainerCell::RemoveExtraSpacing(bool top, bool bottom) cont = (wxHtmlContainerCell*)c; if ( IsEmptyContainer(cont) ) { - cont->SetIndent(0, wxHTML_INDENT_VERTICAL); } + cont->SetIndent(0, wxHTML_INDENT_VERTICAL); + } else { cont->RemoveExtraSpacing(false, true);