diff --git a/include/wx/generic/animate.h b/include/wx/generic/animate.h
index e673fa9928..f2338e1141 100644
--- a/include/wx/generic/animate.h
+++ b/include/wx/generic/animate.h
@@ -139,6 +139,10 @@ protected:
     wxBitmap      m_backingStore;     // The frames are drawn here and then blitted
                                       // on the screen
 
+    int m_scalePosX;
+    int m_scalePosY;
+    int m_scaleWidth;
+    int m_scaleHeight;
 private:
     // True if we need to show the next frame after painting the current one.
     bool m_needToShowNextFrame = false;
diff --git a/include/wx/htmllbox.h b/include/wx/htmllbox.h
index 969f32c304..c81987e328 100644
--- a/include/wx/htmllbox.h
+++ b/include/wx/htmllbox.h
@@ -132,6 +132,15 @@ protected:
     // ensure that the given item is cached
     void CacheItem(size_t n) const;
 
+protected:
+    // HTML parser we use
+    wxHtmlWinParser *m_htmlParser;
+
+#if wxUSE_FILESYSTEM
+    // file system used by m_htmlParser
+    wxFileSystem m_filesystem;
+#endif // wxUSE_FILESYSTEM
+
 private:
     // wxHtmlWindowInterface methods:
     virtual void SetHTMLWindowTitle(const wxString& title) override;
@@ -172,14 +181,6 @@ private:
     // this class caches the pre-parsed HTML to speed up display
     wxHtmlListBoxCache *m_cache;
 
-    // HTML parser we use
-    wxHtmlWinParser *m_htmlParser;
-
-#if wxUSE_FILESYSTEM
-    // file system used by m_htmlParser
-    wxFileSystem m_filesystem;
-#endif // wxUSE_FILESYSTEM
-
     // rendering style for the parser which allows us to customize our colours
     wxHtmlListBoxStyle *m_htmlRendStyle;
 
diff --git a/src/aui/framemanager.cpp b/src/aui/framemanager.cpp
index c88e3070da..466c8ba01e 100644
--- a/src/aui/framemanager.cpp
+++ b/src/aui/framemanager.cpp
@@ -2394,6 +2394,7 @@ void wxAuiManager::Update()
                 p.window->Refresh();
                 p.window->Update();
             }
+            p.BestSize(p.rect.GetSize());
         }
     }
 
@@ -3773,6 +3774,13 @@ void wxAuiManager::OnLeftDown(wxMouseEvent& event)
 {
     m_currentDragItem = -1;
 
+    // We get incorrect coordinates of the mouse position when
+    // there's a pane attached to the left side,
+    // use screen coordinates to get correct local position
+    wxPoint pt = ::wxGetMousePosition();
+    wxPoint client_pt = m_frame->ScreenToClient(pt);
+    event.SetPosition(client_pt);
+
     wxAuiDockUIPart* part = HitTest(event.GetX(), event.GetY());
     if (part)
     {
diff --git a/src/generic/animateg.cpp b/src/generic/animateg.cpp
index 365ffd0579..52672ef8b4 100644
--- a/src/generic/animateg.cpp
+++ b/src/generic/animateg.cpp
@@ -174,6 +174,7 @@ void wxGenericAnimationCtrl::Init()
     m_currentFrame = 0;
     m_looped = false;
     m_isPlaying = false;
+    m_scalePosX = m_scalePosY = m_scaleWidth = m_scaleHeight = 0;
 
     // use the window background colour by default to be consistent
     // with the GTK+ native version
@@ -274,6 +275,9 @@ void wxGenericAnimationCtrl::SetAnimation(const wxAnimationBundle& animations)
     if (!this->HasFlag(wxAC_NO_AUTORESIZE))
         FitToAnimation();
 
+    //wxSizeEvent e;
+    //OnSize(e);
+
     DisplayStaticImage();
 }
 
@@ -354,18 +358,14 @@ bool wxGenericAnimationCtrl::RebuildBackingStoreUpToFrame(unsigned int frame)
 {
     // if we've not created the backing store yet or it's too
     // small, then recreate it
-    wxSize sz = m_animation.GetSize(),
-           winsz = GetClientSize();
-    int w = wxMin(sz.GetWidth(), winsz.GetWidth());
-    int h = wxMin(sz.GetHeight(), winsz.GetHeight());
-
-    if ( !m_backingStore.IsOk() ||
-            m_backingStore.GetWidth() < w || m_backingStore.GetHeight() < h )
+    wxSize sz = m_animation.GetSize();
+    int w = sz.GetWidth(), h = sz.GetHeight();
+    if (!m_backingStore.IsOk() ||
+        m_backingStore.GetWidth() != w || m_backingStore.GetHeight() != h)
     {
         if (!m_backingStore.Create(w, h))
             return false;
     }
-
     wxMemoryDC dc;
     dc.SelectObject(m_backingStore);
 
@@ -496,7 +496,11 @@ void wxGenericAnimationCtrl::DrawCurrentFrame(wxDC& dc)
     wxASSERT( m_backingStore.IsOk() );
 
     // m_backingStore always contains the current frame
-    dc.DrawBitmap(m_backingStore, 0, 0, true /* use mask in case it's present */);
+    if (m_scaleWidth > 0 && m_scaleHeight > 0)
+    {
+        wxBitmap bitmap(m_backingStore.ConvertToImage().Scale(m_scaleWidth, m_scaleHeight));
+        dc.DrawBitmap(bitmap, m_scalePosX, m_scalePosY, true);
+    }
 }
 
 void wxGenericAnimationCtrl::DisposeToBackground()
@@ -544,7 +548,11 @@ void wxGenericAnimationCtrl::OnPaint(wxPaintEvent& WXUNUSED(event))
         // NOTE: we draw the bitmap explicitly ignoring the mask (if any);
         //       i.e. we don't want to combine the backing store with the
         //       possibly wrong preexisting contents of the window!
-        dc.DrawBitmap(m_backingStore, 0, 0, false /* no mask */);
+        if (m_scaleWidth > 0 && m_scaleHeight > 0)
+        {
+            wxBitmap bitmap(m_backingStore.ConvertToImage().Scale(m_scaleWidth, m_scaleHeight));
+            dc.DrawBitmap(bitmap, m_scalePosX, m_scalePosY, false);
+        }
     }
     else
     {
@@ -605,6 +613,19 @@ void wxGenericAnimationCtrl::OnSize(wxSizeEvent &WXUNUSED(event))
             if (!RebuildBackingStoreUpToFrame(m_currentFrame))
                 Stop();     // in case we are playing
         }
+        int w, h, srcW, srcH;
+        wxSize srcSize = m_animation.GetSize();
+        GetClientSize(&w, &h);
+        srcW = srcSize.GetWidth();
+        srcH = srcSize.GetHeight();
+        m_scaleWidth = srcW * h / srcH;
+        m_scaleHeight = srcH * w / srcW;
+        if (m_scaleWidth > w)
+            m_scaleWidth = w;
+        else
+            m_scaleHeight = h;
+        m_scalePosX = (w - m_scaleWidth) / 2;
+        m_scalePosY = (h - m_scaleHeight) / 2;
     }
 }
 
diff --git a/src/generic/scrlwing.cpp b/src/generic/scrlwing.cpp
index 148722a598..e1b31fe583 100644
--- a/src/generic/scrlwing.cpp
+++ b/src/generic/scrlwing.cpp
@@ -536,20 +536,11 @@ void wxScrollHelperBase::HandleOnScroll(wxScrollWinEvent& event)
         m_win->SetScrollPos(wxVERTICAL, m_yScrollPosition);
     }
 
-    if ( needsRefresh )
-    {
-        m_targetWindow->Refresh(true, GetScrollRect());
-    }
-    else
+    m_targetWindow->Refresh(true, GetScrollRect());
+    if (!needsRefresh)
     {
         m_targetWindow->ScrollWindow(dx, dy, GetScrollRect());
     }
-#ifdef __WXUNIVERSAL__
-    if (m_win != m_targetWindow)
-    {
-        m_win->Refresh(true, GetScrollRect());
-    }
-#endif // __WXUNIVERSAL__
 }
 
 int wxScrollHelperBase::CalcScrollInc(wxScrollWinEvent& event)
diff --git a/src/html/htmlwin.cpp b/src/html/htmlwin.cpp
index 1f5f138fe9..eaa6db1809 100644
--- a/src/html/htmlwin.cpp
+++ b/src/html/htmlwin.cpp
@@ -493,7 +493,6 @@ bool wxHtmlWindow::DoSetPage(const wxString& source)
     // ...and run the parser on it:
     wxClientDC dc(this);
     dc.SetMapMode(wxMM_TEXT);
-    SetBackgroundColour(wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW));
     SetBackgroundImage(wxNullBitmap);
 
     double pixelScale = 1.0;
diff --git a/src/html/m_image.cpp b/src/html/m_image.cpp
index cee2fdfc9d..67980a98ca 100644
--- a/src/html/m_image.cpp
+++ b/src/html/m_image.cpp
@@ -312,6 +312,8 @@ private:
     wxBitmap           *m_bitmap;
     int                 m_align;
     int                 m_bmpW, m_bmpH;
+    wxBitmap            m_cachedBmp;
+    int                 m_bmpMaxW, m_bmpMaxH;
     bool                m_bmpWpercent:1;
     bool                m_bmpHpresent:1;
     bool                m_showFrame:1;
@@ -365,6 +367,7 @@ wxHtmlImageCell::wxHtmlImageCell(wxHtmlWindowInterface *windowIface,
     m_bitmap = nullptr;
     m_bmpW   = w;
     m_bmpH   = h;
+    m_bmpMaxW = m_bmpMaxH = wxDefaultCoord;
     m_align  = align;
     m_bmpWpercent = wpercent;
     m_bmpHpresent = hpresent;
@@ -395,20 +398,21 @@ wxHtmlImageCell::wxHtmlImageCell(wxHtmlWindowInterface *windowIface,
                     if ( m_gifDecoder->LoadGIF(*s) == wxGIF_OK )
                     {
                         wxImage img;
-                        if ( m_gifDecoder->ConvertToImage(0, &img) )
-                            SetImage(img);
-
                         readImg = false;
 
                         if ( m_gifDecoder->IsAnimation() )
                         {
                             m_gifTimer = new wxGIFTimer(this);
+                            wxSize sz(m_gifDecoder->GetAnimationSize());
+                            m_bmpMaxW = sz.GetWidth() / scaleHDPI;
+                            m_bmpMaxH = sz.GetHeight() / scaleHDPI;
                             long delay = m_gifDecoder->GetDelay(0);
                             if ( delay == 0 )
                                 delay = 1;
                             m_gifTimer->Start(delay, true);
                         }
-                        else
+                        if (m_gifDecoder->ConvertToImage(0, &img)) SetImage(img, scaleHDPI);
+                        if (!m_gifDecoder->IsAnimation())
                         {
                             wxDELETE(m_gifDecoder);
                         }
@@ -430,19 +434,8 @@ wxHtmlImageCell::wxHtmlImageCell(wxHtmlWindowInterface *windowIface,
         }
         else // input==nullptr, use "broken image" bitmap
         {
-            if ( m_bmpW == wxDefaultCoord && m_bmpH == wxDefaultCoord )
-            {
-                m_bmpW = 29;
-                m_bmpH = 31;
-            }
-            else
-            {
-                m_showFrame = true;
-                if ( m_bmpW == wxDefaultCoord ) m_bmpW = 31;
-                if ( m_bmpH == wxDefaultCoord ) m_bmpH = 33;
-            }
-            m_bitmap =
-                new wxBitmap(wxArtProvider::GetBitmap(wxART_MISSING_IMAGE));
+            wxBitmap missBmp(wxArtProvider::GetBitmap(wxART_MISSING_IMAGE));
+            SetImage(missBmp.ConvertToImage());
         }
     }
     //else: ignore the 0-sized images used sometimes on the Web pages
@@ -460,14 +453,26 @@ void wxHtmlImageCell::SetImage(const wxImage& img, double scaleHDPI)
         ww = img.GetWidth();
         hh = img.GetHeight();
 
-        if ( m_bmpW == wxDefaultCoord)
-            m_bmpW = ww / scaleHDPI;
-        if ( m_bmpH == wxDefaultCoord)
-            m_bmpH = hh / scaleHDPI;
+        if (m_bmpMaxW == wxDefaultCoord)
+            m_bmpMaxW = ww / scaleHDPI;
+        if (m_bmpMaxH == wxDefaultCoord)
+            m_bmpMaxH = hh / scaleHDPI;
+        if (m_bmpW == wxDefaultCoord && m_bmpH == wxDefaultCoord)
+        {
+            m_bmpW = m_bmpMaxW;
+            m_bmpH = m_bmpMaxH;
+        }
+        else if (m_bmpW == wxDefaultCoord)
+            m_bmpW = m_bmpMaxW * m_bmpH / m_bmpMaxH;
+        else if (m_bmpH == wxDefaultCoord)
+            m_bmpH = m_bmpMaxH * m_bmpW / m_bmpMaxW;
 
         // On a Mac retina screen, we might have found a @2x version of the image,
         // so specify this scale factor.
-        m_bitmap = new wxBitmap(img, -1, scaleHDPI);
+        if (ww == m_bmpMaxW && hh == m_bmpMaxH)
+            m_bitmap = new wxBitmap(img, -1, scaleHDPI);
+        else
+            m_bitmap = new wxBitmap(img.Size(wxSize(m_bmpMaxW, m_bmpMaxH), wxPoint(0, 0)), -1, scaleHDPI);
     }
 #endif
 }
@@ -492,7 +497,6 @@ void wxHtmlImageCell::AdvanceAnimation(wxTimer *timer)
     if (m_nCurrFrame == m_gifDecoder->GetFrameCount())
         m_nCurrFrame = 0;
 
-    if ( m_physX == wxDefaultCoord )
     {
         m_physX = m_physY = 0;
         for (wxHtmlCell *cell = this; cell; cell = cell->GetParent())
@@ -511,18 +515,24 @@ void wxHtmlImageCell::AdvanceAnimation(wxTimer *timer)
          m_gifDecoder->ConvertToImage(m_nCurrFrame, &img) )
     {
 #if !defined(__WXMSW__) || wxUSE_WXDIB
-        if ( m_gifDecoder->GetFrameSize(m_nCurrFrame) != wxSize(m_Width, m_Height) ||
-             m_gifDecoder->GetFramePosition(m_nCurrFrame) != wxPoint(0, 0) )
+        if (m_gifDecoder->GetFramePosition(m_nCurrFrame) != wxPoint(0, 0))
         {
-            wxBitmap bmp(img);
+            wxBitmap bmp(img.Size(wxSize(m_bmpMaxW, m_bmpMaxH), m_gifDecoder->GetFramePosition(m_nCurrFrame)));
             wxMemoryDC dc;
             dc.SelectObject(*m_bitmap);
-            dc.DrawBitmap(bmp, m_gifDecoder->GetFramePosition(m_nCurrFrame),
-                          true /* use mask */);
+            dc.DrawBitmap(bmp, 0, 0, true);
         }
         else
 #endif
             SetImage(img);
+
+        if (m_Width > 0 && m_Height > 0)
+        {
+            if (m_bitmap->GetWidth() == m_Width && m_bitmap->GetHeight() == m_Height)
+                m_cachedBmp = *m_bitmap;
+            else
+                m_cachedBmp = wxBitmap(m_bitmap->ConvertToImage().Scale(m_Width, m_Height));
+        }
         win->Refresh(img.HasMask(), &rect);
     }
 
@@ -549,6 +559,15 @@ void wxHtmlImageCell::Layout(int w)
         m_Width  = static_cast<int>(m_scale*m_bmpW);
         m_Height = static_cast<int>(m_scale*m_bmpH);
     }
+    if (m_Width < 0) m_Width = 0;
+    if (m_Height < 0) m_Height = 0;
+    if (m_bitmap && m_Width > 0 && m_Height > 0)
+    {
+        if (m_bitmap->GetWidth() == m_Width && m_bitmap->GetHeight() == m_Height)
+            m_cachedBmp = *m_bitmap;
+        else
+            m_cachedBmp = wxBitmap(m_bitmap->ConvertToImage().Scale(m_Width, m_Height));
+    }
 
     switch (m_align)
     {
@@ -589,49 +608,9 @@ void wxHtmlImageCell::Draw(wxDC& dc, int x, int y,
         dc.SetBrush(*wxTRANSPARENT_BRUSH);
         dc.SetPen(*wxBLACK_PEN);
         dc.DrawRectangle(x + m_PosX, y + m_PosY, m_Width, m_Height);
-        x++;
-        y++;
-    }
-    if ( m_bitmap && m_Width && m_Height )
-    {
-        // We add in the scaling from the desired bitmap width
-        // and height, so we only do the scaling once.
-        double imageScaleX = 1.0;
-        double imageScaleY = 1.0;
-
-        // Optimisation for Windows: WIN32 scaling for window DCs is very poor,
-        // so unless we're using a printer DC, do the scaling ourselves.
-#if defined(__WXMSW__) && wxUSE_IMAGE
-        if (m_Width != m_bitmap->GetWidth()
-    #if wxUSE_PRINTING_ARCHITECTURE
-            && !dc.IsKindOf(CLASSINFO(wxPrinterDC))
-    #endif
-           )
-        {
-            wxImage image(m_bitmap->ConvertToImage());
-            if (image.HasMask())
-            {
-                // Convert the mask to an alpha channel or scaling won't work correctly
-                image.InitAlpha();
-            }
-            image.Rescale(m_Width, m_Height, wxIMAGE_QUALITY_HIGH);
-            (*m_bitmap) = wxBitmap(image);
-        }
-#endif
-
-        if (m_Width != m_bitmap->GetLogicalWidth())
-            imageScaleX = (double) m_Width / (double) m_bitmap->GetLogicalWidth();
-        if (m_Height != m_bitmap->GetLogicalHeight())
-            imageScaleY = (double) m_Height / (double) m_bitmap->GetLogicalHeight();
-
-        double us_x, us_y;
-        dc.GetUserScale(&us_x, &us_y);
-        dc.SetUserScale(us_x * imageScaleX, us_y * imageScaleY);
-
-        dc.DrawBitmap(*m_bitmap, (int) ((x + m_PosX) / (imageScaleX)),
-                                 (int) ((y + m_PosY) / (imageScaleY)), true);
-        dc.SetUserScale(us_x, us_y);
     }
+    if (m_cachedBmp.IsOk())
+        dc.DrawBitmap(m_cachedBmp, x + m_PosX, y + m_PosY, true);
 }
 
 wxHtmlLinkInfo *wxHtmlImageCell::GetLink( int x, int y ) const
diff --git a/src/html/m_links.cpp b/src/html/m_links.cpp
index f9e197f31e..963c2439a0 100644
--- a/src/html/m_links.cpp
+++ b/src/html/m_links.cpp
@@ -81,7 +81,8 @@ TAG_HANDLER_BEGIN(A, "A")
             // set default styles, might get overridden by ApplyStyle
             m_WParser->SetActualColor(m_WParser->GetLinkColor());
             m_WParser->GetContainer()->InsertCell(new wxHtmlColourCell(m_WParser->GetLinkColor()));
-            m_WParser->SetFontUnderlined(true);
+            if (!(tag.HasParam(wxT("CLASS")) && tag.GetParam(wxT("CLASS")).IsSameAs(wxT("PLAIN"), false)))
+                m_WParser->SetFontUnderlined(true);
             m_WParser->GetContainer()->InsertCell(new wxHtmlFontCell(m_WParser->CreateCurrentFont()));
             m_WParser->SetLink(wxHtmlLinkInfo(href, target));
 
diff --git a/src/html/winpars.cpp b/src/html/winpars.cpp
index 07bc8ef592..dc0ec1310c 100644
--- a/src/html/winpars.cpp
+++ b/src/html/winpars.cpp
@@ -47,6 +47,7 @@ wxHtmlWinParser::wxHtmlWinParser(wxHtmlWindowInterface *wndIface)
     m_whitespaceMode = Whitespace_Normal;
     m_lastWordCell = nullptr;
     m_posColumn = 0;
+    m_LinkColor.Set(0, 0, 0xFF);
 
     {
         int i, j, k, l, m;
@@ -193,7 +194,6 @@ void wxHtmlWinParser::InitParser(const wxString& source)
 
     m_UseLink = false;
     m_Link = wxHtmlLinkInfo( wxEmptyString );
-    m_LinkColor = wxPrivate::GetLinkColour();
 
     // if an HTML window interface is connected to this parser,
     // then use its control background color and the system
@@ -257,36 +257,6 @@ wxFSFile *wxHtmlWinParser::OpenURL(wxHtmlURLType type,
     for (;;)
     {
         wxString myfullurl(myurl);
-
-        // consider url as absolute path first
-        wxURI current(myurl);
-        myfullurl = current.BuildUnescapedURI();
-
-        // if not absolute then ...
-        if( current.IsRelative() )
-        {
-            wxString basepath = GetFS()->GetPath();
-            wxURI base(basepath);
-
-            // ... try to apply base path if valid ...
-            if( !base.IsReference() )
-            {
-                wxURI path(myfullurl);
-                path.Resolve( base );
-                myfullurl = path.BuildUnescapedURI();
-            }
-            else
-            {
-                // ... or force such addition if not included already
-                if( !current.GetPath().Contains(base.GetPath()) )
-                {
-                    basepath += myurl;
-                    wxURI connected( basepath );
-                    myfullurl = connected.BuildUnescapedURI();
-                }
-            }
-        }
-
         wxString redirect;
         status = m_windowInterface->OnHTMLOpeningURL(type, myfullurl, &redirect);
         if ( status != wxHTML_REDIRECT )
