Usermode/AxWin4 - Shared buffers working, added DrawCtrl code
[tpg/acess2.git] / Usermode / Applications / axwin4_src / Server / draw_control.cpp
diff --git a/Usermode/Applications/axwin4_src/Server/draw_control.cpp b/Usermode/Applications/axwin4_src/Server/draw_control.cpp
new file mode 100644 (file)
index 0000000..264165f
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Acess2 GUI v4
+ * - By John Hodge (thePowersGang)
+ *
+ * draw_control.cpp
+ * - Common "Control" Drawing
+ *
+ * Handles drawing of resizable controls defined by a bitmap and four region sizes
+ */
+#include <draw_control.hpp>
+
+// === CODE ===
+namespace AxWin {
+
+CControl::CControl(int EdgeX, int FillX, int InnerX, int EdgeY, int FillY, int InnerY, ::std::vector<uint32_t>&& data):
+       m_edge_x(EdgeX),
+       m_fill_x(FillX),
+       m_inner_x(InnerX),
+       m_edge_y(EdgeY),
+       m_fill_y(FillY),
+       m_inner_y(InnerY),
+       m_data(data)
+{
+       
+}
+
+void CControl::Render(CSurface& dest, const CRect& rect) const
+{
+       if( rect.m_w < m_edge_x*2 + m_fill_x*2 + m_inner_x )
+               return ;
+       if( rect.m_h < m_edge_y*2 + m_fill_y*2 + m_inner_y )
+               return ;
+       
+       const int ctrl_width = m_edge_x + m_fill_x + m_inner_x + (m_inner_x ? m_fill_x : 0) + m_edge_x;
+       
+       const int top_fill_end = rect.m_h / 2 - m_inner_y;
+       const int bot_fill_start = top_fill_end + m_inner_y;
+       const int bot_fill_end   = rect.m_h - m_edge_y;
+       
+       ::std::vector<uint32_t> scanline( rect.m_w );
+        int    y = 0;
+        int    base_ofs = 0;
+       // EdgeY
+       for( int i = 0; i < m_edge_y; i ++ )
+               renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]);
+       base_ofs += m_edge_y;
+       // FillY
+       while( y < top_fill_end )
+       {
+               for( int i = 0; i < m_fill_y && y < top_fill_end; i ++ )
+                       renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]);
+       }
+       base_ofs += m_fill_y;
+       // InnerY
+       if( m_inner_y > 0 )
+       {
+               for( int i = 0; i < m_inner_y; i ++ )
+                       renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]);
+               base_ofs += m_inner_y;
+       }
+       else
+       {
+               base_ofs -= m_fill_x;
+       }
+       // FillY
+       while( y < bot_fill_end )
+       {
+               for( int i = 0; i < m_fill_y && y < bot_fill_end; i ++ )
+                       renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]);
+       }
+       base_ofs += m_fill_y;
+       // EdgeY
+       for( int i = 0; i < m_edge_y; i ++ )
+               renderLine(dest, y++, scanline, rect, &m_data[(base_ofs+i)*ctrl_width]);
+       base_ofs += m_edge_y;
+}
+
+void CControl::renderLine(CSurface& dest, int y, ::std::vector<uint32_t>& scanline, const CRect& rect, const uint32_t* ctrl_line) const
+{
+       const int left_fill_end = rect.m_w / 2 - m_inner_x;
+       const int right_fill_end = rect.m_w - m_edge_x;
+       
+        int    x = 0;
+        int    base_ofs = 0;
+       // EdgeX
+       for( int i = 0; i < m_edge_x; i ++ )
+               scanline[x++] = ctrl_line[base_ofs + i];
+       base_ofs += m_edge_x;
+       // FillX
+       while( x < left_fill_end )
+       {
+               for( int i = 0; i < m_fill_x && x < left_fill_end; i ++ )
+                       scanline[x++] = ctrl_line[base_ofs + i];
+       }
+       base_ofs += m_fill_x;
+       // InnerX
+       if( m_inner_x > 0 )
+       {
+               for( int i = 0; i < m_inner_x; i ++ )
+                       scanline[x++] = ctrl_line[base_ofs + i];
+               base_ofs += m_inner_x;
+       }
+       else
+       {
+               base_ofs -= m_fill_x;
+       }
+       // FillX
+       while( x < right_fill_end )
+       {
+               for( int i = 0; i < m_fill_x && x < right_fill_end; i ++ )
+                       scanline[x++] = ctrl_line[base_ofs + i];
+       }
+       base_ofs += m_fill_x;
+       // EdgeX
+       for( int i = 0; i < m_edge_x; i ++ )
+               scanline[x++] = ctrl_line[base_ofs + i];
+       base_ofs += m_edge_x;
+       
+       dest.DrawScanline(rect.m_y + y, rect.m_x, rect.m_w, scanline.data());
+}
+
+// ---- Standard Controls ---
+// Standard button control
+CControl StdButton(2, 1, 0, 2, 1, 0, ::std::vector<uint32_t> {
+       0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0,
+       0xC0C0C0, 0xFFD0D0, 0xFFD0D0, 0xFFD0D0, 0xC0C0C0,
+       0xC0C0C0, 0xFFD0D0, 0xFFD0D0, 0xFFD0D0, 0xC0C0C0,
+       0xC0C0C0, 0xFFD0D0, 0xFFD0D0, 0xFFD0D0, 0xC0C0C0,
+       0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0, 0xC0C0C0,
+       });
+
+// Text Area
+CControl StdText(2, 1, 0, 2, 1, 0, ::std::vector<uint32_t> {
+       0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+       0x000000, 0xA0A0A0, 0x0A0000, 0xA0A0A0, 0x000000,
+       0x000000, 0xA0A0A0, 0xFFFFFF, 0xA0A0A0, 0x000000,
+       0x000000, 0xA0A0A0, 0x0A0000, 0xA0A0A0, 0x000000,
+       0x000000, 0x000000, 0x000000, 0x000000, 0x000000,
+       });
+
+const CControl* CControl::GetByName(const ::std::string& name)
+{
+       if( name == "StdButton" )
+               return &StdButton;
+       if( name == "StdText" )
+               return &StdText;
+       // TODO: Use another exception
+       return nullptr;
+}
+
+const CControl* CControl::GetByID(uint16_t id)
+{
+       switch(id)
+       {
+       case 0x00:      return &StdButton;
+       case 0x01:      return &StdText;
+       default:        return nullptr;
+       }
+}
+
+};     // AxWin
+

UCC git Repository :: git.ucc.asn.au