Bugfixes for CPU rendering
[ipdf/code.git] / src / objectrenderer.cpp
index ff40b1f..e55dbbb 100644 (file)
@@ -4,6 +4,9 @@
  */
 
 #include "objectrenderer.h"
+#include "view.h"
+
+using namespace std;
 
 namespace IPDF
 {
@@ -33,10 +36,24 @@ void ObjectRenderer::RenderUsingGPU()
        glDrawElements(GL_LINES, m_indexes.size()*2, GL_UNSIGNED_INT, 0);
 }
 
+/**
+ * Helper structuretransforms coordinates to pixels
+ */
+
+ObjectRenderer::CPURenderBounds::CPURenderBounds(const Rect & bounds, const View & view, const CPURenderTarget & target)
+{
+       Rect view_bounds = view.TransformToViewCoords(bounds);
+       x = view_bounds.x * Real(target.w);
+       y = view_bounds.y * Real(target.h);
+       w = view_bounds.w * Real(target.w);
+       h = view_bounds.h * Real(target.h);
+       Debug("CPURenderBounds %s -> %s -> {%li,%li,%li,%li}", bounds.Str().c_str(), view_bounds.Str().c_str(), x, y, w, h);
+}
+
 /**
  * Default implementation for rendering using CPU
  */
-void ObjectRenderer::RenderUsingCPU()
+void ObjectRenderer::RenderUsingCPU(const Objects & objects, const View & view, const CPURenderTarget & target)
 {
        Error("Cannot render objects of type %d on CPU", m_type);
 }
@@ -95,4 +112,131 @@ void ObjectRenderer::FinaliseBuffers()
        // Nothing is necessary for CPU rendering
 }
 
+
+/**
+ * Rectangle (filled)
+ */
+void RectFilledRenderer::RenderUsingCPU(const Objects & objects, const View & view, const CPURenderTarget & target)
+{
+       for (unsigned i = 0; i < m_indexes.size(); ++i)
+       {
+               CPURenderBounds bounds(objects.bounds[m_indexes[i]], view, target);
+               for (int64_t x = max(0L, bounds.x); x <= min(bounds.x+bounds.w, target.w-1); ++x)
+               {
+                       for (int64_t y = max(0L, bounds.y); y <= min(bounds.y+bounds.h, target.h-1); ++y)
+                       {
+                               int index = (x+target.w*y)*4;
+                               target.pixels[index+0] = 0;
+                               target.pixels[index+1] = 0;
+                               target.pixels[index+2] = 0;
+                               target.pixels[index+3] = 255;
+                       }
+               }
+       }
+}
+
+/**
+ * Rectangle (outine)
+ */
+void RectOutlineRenderer::RenderUsingCPU(const Objects & objects, const View & view, const CPURenderTarget & target)
+{
+       for (unsigned i = 0; i < m_indexes.size(); ++i)
+       {
+               CPURenderBounds bounds(objects.bounds[m_indexes[i]], view, target);
+               for (int64_t x = max(0L, bounds.x); x <= min(bounds.x+bounds.w, target.w-1); ++x)
+               {
+                       int64_t top = (x+target.w*bounds.y)*4;
+                       int64_t bottom = (x+target.w*(bounds.y+bounds.h))*4;
+
+                       if (top >= 0L && top <4*target.w*target.h)
+                       {
+                               for (int j = 0; j < 3; ++j)
+                                       target.pixels[top+j] = 0;
+                               target.pixels[top+3] = 255;
+                       }
+                       if (bottom >= 0L && bottom <4*target.w*target.h)
+                       {
+                               for (int j = 0; j < 3; ++j)
+                                       target.pixels[bottom+j] = 0;
+                               target.pixels[bottom+3] = 255;
+                       }
+               }
+
+               for (int64_t y = max(0L, bounds.y); y <= min(bounds.y+bounds.h, target.h-1); ++y)
+               {
+                       int64_t left = (bounds.x >= 0L && bounds.x < target.w) ? (bounds.x + target.w*y)*4 : -1L;
+                       int64_t right = (bounds.x+bounds.w >= 0L && bounds.x+bounds.w < target.w) ? (bounds.x+bounds.w + target.w*y)*4 : -1L;
+                       if (left >= 0L && left <4*target.w*target.h)
+                       {
+                               for (int j = 0; j < 3; ++j)
+                                       target.pixels[left+j] = 0;
+                               target.pixels[left+3] = 255;
+                       }
+                       if (right >= 0L && right <4*target.w*target.h)
+                       {
+                               for (int j = 0; j < 3; ++j)
+                                       target.pixels[right+j] = 0;
+                               target.pixels[right+3] = 255;
+                       }
+               }
+       }
+}
+
+/**
+ * Circle (filled)
+ */
+void CircleFilledRenderer::RenderUsingCPU(const Objects & objects, const View & view, const CPURenderTarget & target)
+{
+       for (unsigned i = 0; i < m_indexes.size(); ++i)
+       {
+               CPURenderBounds bounds(objects.bounds[m_indexes[i]], view, target);
+               int64_t centre_x = bounds.x + bounds.w / 2;
+               int64_t centre_y = bounds.y + bounds.h / 2;
+               
+               Debug("Centre is %d, %d", centre_x, centre_y);
+               Debug("Bounds are %d,%d,%d,%d", bounds.x, bounds.y, bounds.w, bounds.h);
+               Debug("Windos is %d,%d", target.w, target.h);
+               for (int64_t x = max(0L, bounds.x); x <= min(bounds.x+bounds.w, target.w-1); ++x)
+               {
+                       for (int64_t y = max(0L, bounds.y); y <= min(bounds.y + bounds.h, target.h-1); ++y)
+                       {
+                               double dx = 2.0*(double)(x - centre_x)/(double)(bounds.w);
+                               double dy = 2.0*(double)(y - centre_y)/(double)(bounds.h);
+                               int64_t index = (x+target.w*y)*4;
+                               
+                               if (dx*dx + dy*dy <= 1.0)
+                               {
+                                       target.pixels[index+0] = 0;
+                                       target.pixels[index+1] = 0;
+                                       target.pixels[index+2] = 0;
+                                       target.pixels[index+3] = 255;
+
+                               }
+                       }
+               }
+       }
+}
+
+
+/**
+ * For debug, save pixels to bitmap
+ */
+void ObjectRenderer::SaveBMP(const CPURenderTarget & target, const char * filename)
+{
+       SDL_Surface * surf = SDL_CreateRGBSurfaceFrom(target.pixels, target.w, target.h, 8*4, target.w*4,
+       #if SDL_BYTEORDER == SDL_LIL_ENDIAN
+               0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
+       #else
+               0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
+       #endif //SDL_BYTEORDER  
+       );      
+       if (surf == NULL)
+               Fatal("SDL_CreateRGBSurfaceFrom(pixels...) failed - %s", SDL_GetError());
+       if (SDL_SaveBMP(surf, filename) != 0)
+               Fatal("SDL_SaveBMP failed - %s", SDL_GetError());
+
+       // Cleanup
+       SDL_FreeSurface(surf);
+}
+
 }

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