diff --git a/bin/Makefile b/bin/Makefile index ae5016e..7a2f8e9 100644 --- a/bin/Makefile +++ b/bin/Makefile @@ -1,8 +1,7 @@ # $Id: Makefile 121 2016-01-14 03:18:20Z reddawg $ # The System Makefile (C) 2002 The UbixOS Project -all: init-bin login-bin shell-bin clock-bin cp-bin fdisk-bin format-bin disklabel-bin ubistry-bin ttyd-bin stat-bin -# muffin-bin +all: init-bin login-bin shell-bin clock-bin cp-bin fdisk-bin format-bin disklabel-bin ubistry-bin ttyd-bin stat-bin muffin-bin # cat-bin # MrOlsen (2016-01-11) ERROR: weird it didnt like -elf rtld-elf-bin # MrOlsen (2016-01-11) NOTE: edit-bin diff --git a/bin/muffin/Makefile b/bin/muffin/Makefile index 8e8fa19..bbcf2e7 100644 --- a/bin/muffin/Makefile +++ b/bin/muffin/Makefile @@ -2,11 +2,12 @@ # Application Makefile (C) 2002 The UbixOS Project # Include Global 'Source' Options -include ../../Makefile.incl -include ../Makefile.incl +#include ../../Makefile.incl +#include ../Makefile.incl #Compiler Flags -CFLAGS = -DNOBOOL -fno-builtin -fno-exceptions -nostdlib -nostdinc +CFLAGS = +# -DNOBOOL -fno-builtin -fno-exceptions #Linker LD = ld @@ -21,14 +22,16 @@ OBJS = main.o #Libraries -LIBRARIES2 = ../../lib/objgfx40/*.o ../../lib/libcpp/*.o +LIBRARIES2 = ../../lib/objgfx/*.o -lstdc++ -lm #Include -INCLUDE = -I../../lib/libc/include -I../../lib/libcpp/include -I../../lib/objgfx40 +INCLUDE = -I../../lib/objgfx + +STARTUP= # Link The Binary $(BINARY) : $(OBJS) - $(CC) $(CFLAGS) -o ${BUILD_DIR}/bin/$@ $(STARTUP) $(LIBRARIES) $(LIBRARIES2) $(OBJS) + $(CC) $(CFLAGS) -o $@ $(STARTUP) $(LIBRARIES) $(LIBRARIES2) $(OBJS) strip $(BINARY) # Compile the source files diff --git a/bin/muffin/main.cc b/bin/muffin/main.cc index 874f882..ed12376 100644 --- a/bin/muffin/main.cc +++ b/bin/muffin/main.cc @@ -26,7 +26,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include +#include extern "C" { #include #include @@ -38,7 +38,7 @@ uInt16 i = 0x0; uInt16 ii = 0x0; uInt16 iii = 0x0; - if (fork() == 0x0) { + //if (fork() == 0x0) { window->vCreate(); window->vSDECommand(1); while (1) { @@ -58,6 +58,6 @@ } } window->vSDECommand(4); - } + //} return(0); } diff --git a/lib/objgfx/objgfx.cpp b/lib/objgfx/objgfx.cpp index 60eabd6..6b425e9 100644 --- a/lib/objgfx/objgfx.cpp +++ b/lib/objgfx/objgfx.cpp @@ -1,3016 +1,3016 @@ -#include -#include -#include -#include -#include - -#include "ogTypes.h" -#include "ogEdgeTable.h" -#include "ogPixCon.h" -#include "ogPixelFmt.h" -#include "objgfx.h" - -const static ogRGBA8 DEFAULT_PALETTE[256] = - {{0, 0, 0, 255}, // 0 - {0, 0, 170, 255}, - {0, 170, 0, 255}, - {0, 170, 170, 255}, // 3 - {170, 0, 0, 255}, - {170, 0, 170, 255}, - {170, 85, 0, 255}, - {170, 170, 170, 255}, // 7 - {85, 85, 85, 255}, - {85, 85, 255, 255}, - {85, 255, 85, 255}, - {85, 255, 255, 255}, // 11 - {255, 85, 85, 255}, - {255, 85, 255, 255}, - {255, 255, 85, 255}, - {255, 255, 255, 255}, //15 - {16, 16, 16, 255}, // 16 - {32, 32, 32, 255}, - {48, 48, 48, 255}, - {64, 64, 64, 255}, - {80, 80, 80, 255}, - {96, 96, 96, 255}, - {112, 112, 112, 255}, - {128, 128, 128, 255}, - {144, 144, 144, 255}, - {160, 160, 160, 255}, - {176, 176, 176, 255}, - {192, 192, 192, 255}, - {208, 208, 208, 255}, - {224, 224, 224, 255}, - {240, 240, 240, 255}, - {255, 255, 255, 255}, //31 - {59, 0, 0, 255}, // 32 - {79, 0, 0, 255}, - {103, 0, 0, 255}, - {123, 0, 0, 255}, - {143, 7, 7, 255}, - {167, 7, 7, 255}, - {187, 11, 11, 255}, - {211, 15, 15, 255}, - {231, 19, 19, 255}, - {255, 27, 27, 255}, - {255, 59, 59, 255}, - {255, 91, 91, 255}, - {255, 119, 119, 255}, - {255, 151, 151, 255}, - {255, 183, 183, 255}, - {255, 215, 215, 255}, - {55, 55, 0, 255}, // 48 - {71, 71, 0, 255}, - {87, 87, 0, 255}, - {103, 103, 7, 255}, - {119, 119, 7, 255}, - {135, 135, 11, 255}, - {155, 155, 19, 255}, - {171, 171, 23, 255}, - {187, 187, 31, 255}, - {203, 203, 35, 255}, - {219, 219, 43, 255}, - {239, 239, 59, 255}, - {255, 255, 63, 255}, - {255, 255, 127, 255}, - {255, 255, 187, 255}, - {255, 255, 255, 255}, - {0, 43, 0, 255}, // 64 - {0, 63, 0, 255}, - {0, 83, 0, 255}, - {0, 103, 0, 255}, - {7, 127, 7, 255}, - {7, 147, 7, 255}, - {11, 167, 11, 255}, - {15, 187, 15, 255}, - {19, 211, 19, 255}, - {27, 231, 27, 255}, - {59, 235, 59, 255}, - {91, 239, 91, 255}, - {127, 239, 127, 255}, - {159, 243, 159, 255}, - {195, 247, 195, 255}, - {231, 251, 231, 255}, - {0, 55, 55, 255}, // 80 - {0, 71, 71, 255}, - {0, 87, 87, 255}, - {7, 103, 103, 255}, - {7, 119, 119, 255}, - {11, 135, 135, 255}, - {19, 155, 155, 255}, - {23, 171, 171, 255}, - {31, 187, 187, 255}, - {35, 203, 203, 255}, - {43, 219, 219, 255}, - {51, 235, 235, 255}, - {63, 255, 255, 255}, - {127, 255, 255, 255}, - {187, 255, 255, 255}, - {255, 255, 255, 255}, - {15, 15, 55, 255}, // 96 - {19, 19, 79, 255}, - {27, 27, 103, 255}, - {31, 31, 127, 255}, - {35, 35, 155, 255}, - {39, 39, 179, 255}, - {43, 43, 203, 255}, - {47, 47, 227, 255}, - {51, 51, 255, 255}, - {71, 71, 255, 255}, - {91, 91, 255, 255}, - {111, 111, 255, 255}, - {131, 131, 255, 255}, - {151, 151, 255, 255}, - {175, 175, 255, 255}, - {195, 195, 255, 255}, - {59, 51, 59, 255}, // 112 - {79, 63, 79, 255}, - {103, 71, 103, 255}, - {123, 75, 123, 255}, - {143, 75, 143, 255}, - {167, 71, 167, 255}, - {187, 67, 187, 255}, - {211, 55, 211, 255}, - {231, 43, 231, 255}, - {255, 27, 255, 255}, - {255, 59, 255, 255}, - {255, 91, 255, 255}, - {255, 119, 255, 255}, - {255, 151, 255, 255}, - {255, 183, 255, 255}, - {255, 215, 255, 255}, - {59, 51, 59, 255}, // 128 - {71, 59, 71, 255}, - {83, 71, 83, 255}, - {95, 83, 95, 255}, - {111, 95, 111, 255}, - {123, 103, 123, 255}, - {135, 115, 135, 255}, - {147, 127, 147, 255}, - {163, 139, 163, 255}, - {175, 151, 175, 255}, - {187, 159, 187, 255}, - {203, 171, 203, 255}, - {215, 183, 215, 255}, - {227, 191, 227, 255}, - {239, 203, 239, 255}, - {255, 215, 255, 255}, - {55, 27, 27, 255}, // 144 - {71, 35, 35, 255}, - {91, 43, 43, 255}, - {107, 55, 55, 255}, - {127, 67, 67, 255}, - {143, 75, 75, 255}, - {163, 87, 87, 255}, - {179, 99, 99, 255}, - {199, 111, 111, 255}, - {203, 127, 127, 255}, - {211, 139, 139, 255}, - {219, 159, 159, 255}, - {223, 175, 175, 255}, - {231, 191, 191, 255}, - {239, 211, 211, 255}, - {247, 231, 231, 255}, - {91, 63, 27, 255}, // 160 - {111, 75, 31, 255}, - {127, 87, 39, 255}, - {147, 103, 43, 255}, - {167, 115, 51, 255}, - {187, 127, 55, 255}, - {207, 139, 63, 255}, - {227, 155, 67, 255}, - {247, 167, 75, 255}, - {247, 175, 95, 255}, - {247, 183, 119, 255}, - {247, 195, 139, 255}, - {247, 203, 159, 255}, - {247, 215, 183, 255}, - {247, 227, 203, 255}, - {251, 239, 227, 255}, - {63, 63, 31, 255}, // 176 - {75, 75, 35, 255}, - {87, 87, 43, 255}, - {99, 99, 51, 255}, - {115, 115, 55, 255}, - {127, 127, 63, 255}, - {139, 139, 67, 255}, - {151, 151, 75, 255}, - {167, 167, 83, 255}, - {175, 175, 95, 255}, - {183, 183, 107, 255}, - {191, 191, 123, 255}, - {203, 203, 139, 255}, - {211, 211, 159, 255}, - {219, 219, 175, 255}, - {231, 231, 195, 255}, - {27, 59, 47, 255}, // 192 - {31, 75, 59, 255}, - {39, 87, 67, 255}, - {47, 103, 79, 255}, - {55, 119, 91, 255}, - {59, 135, 99, 255}, - {67, 151, 111, 255}, - {71, 167, 119, 255}, - {79, 183, 127, 255}, - {87, 199, 139, 255}, - {91, 215, 147, 255}, - {99, 231, 155, 255}, - {127, 235, 183, 255}, - {163, 239, 211, 255}, - {195, 243, 231, 255}, - {231, 251, 247, 255}, - {23, 55, 55, 255}, // 208 - {31, 71, 71, 255}, - {39, 87, 87, 255}, - {47, 103, 103, 255}, - {55, 119, 119, 255}, - {67, 139, 139, 255}, - {75, 155, 155, 255}, - {87, 171, 171, 255}, - {99, 187, 187, 255}, - {111, 203, 203, 255}, - {123, 223, 223, 255}, - {143, 227, 227, 255}, - {163, 231, 231, 255}, - {183, 235, 235, 255}, - {203, 239, 239, 255}, - {227, 247, 247, 255}, - {39, 39, 79, 255}, // 224 - {47, 47, 91, 255}, - {55, 55, 107, 255}, - {63, 63, 123, 255}, - {71, 71, 139, 255}, - {79, 79, 151, 255}, - {87, 87, 167, 255}, - {99, 99, 183, 255}, - {107, 107, 199, 255}, - {123, 123, 203, 255}, - {139, 139, 211, 255}, - {155, 155, 219, 255}, - {171, 171, 223, 255}, - {187, 187, 231, 255}, - {207, 207, 239, 255}, - {227, 227, 247, 255}, - {63, 27, 63, 255}, // 240 - {75, 31, 75, 255}, - {91, 39, 91, 255}, - {103, 47, 103, 255}, - {119, 51, 119, 255}, - {131, 59, 131, 255}, - {147, 67, 147, 255}, - {163, 75, 163, 255}, - {175, 83, 175, 255}, - {191, 91, 191, 255}, - {199, 107, 199, 255}, - {207, 127, 207, 255}, - {215, 147, 215, 255}, - {223, 171, 223, 255}, - {231, 195, 231, 255}, - {243, 219, 243, 255}}; - -const double ogSurface::INTENSITIES[32] = { - 1.0, // 0 - 0.984250984251, // 1 - 0.968245836552, // 2 - 0.951971638233, // 3 - 0.935414346693, // 4 - 0.938558653544, // 5 - 0.901387818866, // 6 - 0.883883476483, // 7 - 0.866025403784, // 8 - 0.847791247891, // 9 - 0.829156197589, // 10 - 0.810092587301, // 11 - 0.790569415042, // 12 - 0.770551750371, // 13 - 0.75, // 14 - 0.728868986856, // 15 - 0.707106781187, // 16 - 0.684653196881, // 17 - 0.661437827766, // 18 - 0.637377439199, // 19 - 0.612372435696, // 20 - 0.586301969978, // 21 - 0.559016994375, // 22 - 0.53033008589, // 23 - 0.5, // 24 - 0.467707173347, // 25 - 0.433012701892, // 26 - 0.395284707521, // 27 - 0.353553390593, // 28 - 0.306186217848, // 29 - 0.25, // 30 - 0.176776695297 // 31 -}; // INTENSITIES[] - -// ogSurface constructor -ogSurface::ogSurface(void) -{ - version = ogVERSION; - - dataState = ogNone; - buffer = NULL; - lineOfs = NULL; - pal = NULL; - attributes = NULL; - xRes = 0; - yRes = 0; - maxX = 0; - maxY = 0; - bSize = 0; - lSize = 0; - BPP = 0; - bytesPerPix = 0; - pixFmtID = 0; - redShifter = 0; - greenShifter= 0; - blueShifter = 0; - alphaShifter= 0; - redFieldPosition = 0; - greenFieldPosition = 0; - blueFieldPosition = 0; - alphaFieldPosition = 0; - alphaMasker = 0; - lastError = ogOK; - - // Set these function pointers to do nothing (but not crash) - // in case somebody actually calls them. - setPixel = ([] (void * ptr, uInt32 p) -> void { }); - getPixel = ([] (void * ptr) -> uInt32 { return 0; }); -} // ogSurface::ogSurface() - - -void ogSurface::AARawLine(uInt32 x1, uInt32 y1, uInt32 x2, uInt32 y2, uInt32 colour) -{ - /* - * aaRawLine - * - * private method - * - * draws an unclipped anti-aliased line from (x1,y1) to (x2,y2) using colour - * - */ - uInt32 erradj, erracc; - uInt32 erracctmp, intshift, wgt, wgtCompMask; - int32 dx, dy, tmp, xDir, i; - uInt8 r, g, b, a; - uInt32 alphas[32]; - bool oldBlending; - - if (y1 > y2) - { - tmp= y1; - y1 = y2; - y2 = tmp; - - tmp= x1; - x1 = x2; - x2 = tmp; - } // if - - dx = (x2-x1); - if (dx >= 0) xDir=1; else { dx = -dx; xDir=-1; } - // dx = abs(dx); - dy = (y2 - y1); - - if (dy == 0) - { - ogHLine(x1, x2, y1, colour); - return; - } - - if (dx == 0) - { - ogVLine(x1, y1, y2, colour); - return; - } - - ogUnpack(colour, r, g, b, a); - if (!ogIsBlending()) a = 255; - - for (i = 0; i < 32; i++) - { - alphas[i] = static_cast(INTENSITIES[i]*a + 0.5f); - } // for - - oldBlending = ogSetBlending(true); - - RawSetPixel(x1, y1, r, g, b, a); - - // this is incomplete.. diagonal lines don't travel through the - // center of pixels exactly - - do { - - if (dx == dy) - { - for (; dy != 0; dy--) - { - x1 += xDir; - ++y1; - RawSetPixel(x1, y1, r, g, b, a); - } // for - break; // pop out to the bottom and restore the old blending state - } // if dx==dy - - erracc = 0; - intshift = 32-5; - wgt = 12; - wgtCompMask = 31; - - if (dy > dx) { - /* y-major. Calculate 32-bit fixed point fractional part of a pixel that - * X advances every time Y advances 1 pixel, truncating the result so that - * we won't overrun the endpoint along the X axis - */ -#ifndef __UBIXOS__ - erradj = ((uInt64) dx << 32) / (uInt64)dy; -#else - asm volatile ( // fixed - " xor %%eax, %%eax \n" - " div %%ecx \n" - : "=a" (erradj) - : "d" (dx), "c" (dy) - ); -#endif - - while (--dy) { - erracctmp = erracc; - erracc += erradj; - if (erracc <= erracctmp) x1 += xDir; - y1++; // y-major so always advance Y - /* the nbits most significant bits of erracc give us the intensity - * weighting for this pixel, and the complement of the weighting for - * the paired pixel. - */ - wgt = erracc >> intshift; - ogSetPixel(x1, y1, r, g, b, alphas[wgt]); - ogSetPixel(x1+xDir, y1, r, g, b, alphas[wgt ^ wgtCompMask]); - } // while - - } else { - - /* x-major line. Calculate 32-bit fixed-point fractional part of a pixel - * that Y advances each time X advances 1 pixel, truncating the result so - * that we won't overrun the endpoint along the X axis. - */ -#ifndef __UBIXOS__ - erradj = ((uInt64)dy << 32) / (uInt64)dx; -#else - asm volatile( // fixed - " xor %%eax, %%eax \n" - " div %%ecx \n" - : "=a" (erradj) - : "d" (dy), "c" (dx) - ); -#endif - // draw all pixels other than the first and last - while (--dx) { - erracctmp = erracc; - erracc += erradj; - if (erracc <= erracctmp) y1++; - x1 += xDir; // x-major so always advance X - /* the nbits most significant bits of erracc give us the intensity - * weighting for this pixel, and the complement of the weighting for - * the paired pixel. - */ - wgt = erracc >> intshift; - ogSetPixel(x1, y1, r, g, b, alphas[wgt]); - ogSetPixel(x1, y1+1, r, g, b, alphas[wgt ^ wgtCompMask]); - } // while - } // else - RawSetPixel(x2, y2, r, g, b, alphas[wgt]); - - } while (false); - - ogSetBlending(oldBlending); -} // void ogSurface::AARawLine() - -bool ogSurface::ClipLine(int32& x1, int32& y1, int32& x2, int32& y2) -{ - /* - * clipLine() - * - * private method - * - * clips a line to (0,0),(maxX,maxY); returns true if - * the line segment is in bounds, false if none of the line segment is - * on the screen. Uses HJI's line clipping algorithm. - */ - - int32 tx1, ty1, tx2, ty2; - int32 outCode; - uInt32 andResult, orResult; - andResult = 15; - orResult = 0; - outCode = 0; - if (x1 < 0) outCode+=8; - if (x1 > (int32)maxX) outCode+=4; - if (y1 < 0) outCode+=2; - if (y1 > (int32)maxY) outCode++; - - andResult &= outCode; - orResult |= outCode; - outCode = 0; - - if (x2 < 0) outCode+=8; - if (x2 > (int32)maxX) outCode+=4; - if (y2 < 0) outCode+=2; - if (y2 > (int32)maxY) outCode++; - - andResult &= outCode; - orResult |= outCode; - - if (andResult > 0) return false; - if (orResult == 0) return true; - - // some clipping is required here. - - tx1 = x1; - ty1 = y1; - tx2 = x2; - ty2 = y2; - - if (x1 < 0) - { - ty1 = (x2*y1-x1*y2) / (x2-x1); - tx1 = 0; - } // if - else - { - if (x2 < 0) - { - ty2 = (x2*y1-x1*y2) / (x2-x1); - tx2 = 0; - } // elseif - } - - if (x1 > (int32)maxX) - { - ty1 = (y1*(x2-maxX)+y2*(maxX-x1)) / (x2-x1); - tx1 = maxX; - } // if - else - { - if (x2 > (int32)maxX) - { - ty2 = (y1*(x2-maxX)+y2*(maxX-x1)) / (x2-x1); - tx2 = maxX; - } // elseif - } - - if (((ty1 < 0) && (ty2 < 0)) || - ((ty1>(int32)maxY) && (ty2>(int32)maxY))) return false; - - if (ty1 < 0) - { - tx1 = (x1*y2-x2*y1) / (y2-y1); - ty1 = 0; - } // if - else - { - if (ty2 < 0) - { - tx2 = (x1*y2-x2*y1) / (y2-y1); - ty2 = 0; - } // elseif - } - - if (ty1 > (int32)maxY) - { - tx1 = (x1*(y2-maxY)+x2*(maxY-y1)) / (y2-y1); - ty1 = maxY; - } // if - else - { - if (ty2 > (int32)maxY) - { - tx2 = (x1*(y2-maxY)+x2*(maxY-y1)) / (y2-y1); - ty2 = maxY; - } // elseif - } - - if (((uInt32)tx1 > maxX) || ((uInt32)tx2 > maxX)) return false; - - x1 = tx1; - y1 = ty1; - x2 = tx2; - y2 = ty2; - - return true; -} // bool ogSurface::ClipLine() - -uInt32 ogSurface::RawGetPixel(uInt32 x, uInt32 y) -{ - //uInt8* ptr = (uInt8*)buffer + lineOfs[y]; // Pointer to pixel at (0,y). - void * ptr = reinterpret_cast(buffer + lineOfs[y] + x*bytesPerPix); - return getPixel(ptr); -#if 0 - uInt32 result = 0; - uInt32 * buf32; - uInt8 * buf24; - uInt16 * buf16; - uInt8 * buf8; - - switch (bytesPerPix) { - case 4: - buf32 = reinterpret_cast(buffer + lineOfs[y] + x*4); - result = *buf32; - //uInt32 * - // uInt32 * buf = static_cast(buffer + lineOfs[y]) - _asm { - mov eax, this ; - mov edi, x ; - mov ebx, y ; - - shl edi, 2 ; // adjust for pixel size - mov esi, [eax + ogSurface::lineOfs] ; - add edi, [esi + ebx*4] ; - add edi, [eax + ogSurface::buffer] ; - - mov eax, [edi] ; - mov result, eax ; - }; - break; - case 3: - buf24 = (buffer + lineOfs[y] + x); - result = *buf24; - break; - case 2: - buf16 = reinterpret_cast(buffer + lineOfs[y] + x*2); - result = *buf16; - break; - case 1: - buf8 = (buffer + lineOfs[y] + x); - result = *buf8; - break; - } // switch - return result; -#endif -} // uInt32 ogSurface::RawGetPixel() - -// wu's double step line algorithm blatently borrowed from: -// http://www.edepot.com/linewu.html - -void ogSurface::RawLine(uInt32 x1, uInt32 y1, uInt32 x2, uInt32 y2, uInt32 colour) -{ - int32 dy = y2 - y1; - int32 dx = x2 - x1; - int32 stepx, stepy; - - if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; } - if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; } - - RawSetPixel(x1, y1, colour); - RawSetPixel(x2, y2, colour); - - if (dx > dy) - { - int32 length = (dx - 1) >> 2; - int32 extras = (dx - 1) & 3; - int32 incr2 = (dy << 2) - (dx << 1); - - if (incr2 < 0) - { - int32 c = dy << 1; - int32 incr1 = c << 1; - int32 d = incr1 - dx; - - for (int32 i = 0; i < length; i++) - { - x1 += stepx; - x2 -= stepx; - - if (d < 0) - { // Pattern: - RawSetPixel(x1, y1, colour); // - RawSetPixel(x1 += stepx, y1, colour); // x o o - RawSetPixel(x2, y2, colour); // - RawSetPixel(x2 -= stepx, y2, colour); - - d += incr1; - } - else - { - - if (d < c) - { // Pattern: - RawSetPixel(x1, y1, colour); // o - RawSetPixel(x1 += stepx, y1 += stepy, colour); // x o - RawSetPixel(x2, y2, colour); // - RawSetPixel(x2 -= stepx, y2 -= stepy, colour); - } - else - { - RawSetPixel(x1, y1 += stepy, colour); // Pattern: - RawSetPixel(x1 += stepx, y1, colour); // o o - RawSetPixel(x2, y2 -= stepy, colour); // x - RawSetPixel(x2 -= stepx, y2, colour); // - } // else - - d += incr2; - } // else - } // for i - - if (extras > 0) - { - - if (d < 0) - { - RawSetPixel(x1 += stepx, y1, colour); - if (extras > 1) RawSetPixel(x1 += stepx, y1, colour); - if (extras > 2) RawSetPixel(x2 -= stepx, y2, colour); - } - else - if (d < c) { - RawSetPixel(x1 += stepx, y1, colour); - if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); - if (extras > 2) RawSetPixel(x2 -= stepx, y2, colour); - } - else - { - RawSetPixel(x1 += stepx, y1 += stepy, colour); - if (extras > 1) RawSetPixel(x1 += stepx, y1, colour); - if (extras > 2) RawSetPixel(x2 -= stepx, y2 -= stepy, colour); - } - } // if extras > 0 - } - else - { - int32 c = (dy - dx) << 1; - int32 incr1 = c << 1; - int32 d = incr1 + dx; - - for (int32 i = 0; i < length; i++) - { - x1 += stepx; - x2 -= stepx; - - if (d > 0) - { - RawSetPixel(x1, y1 += stepy, colour); // Pattern: - RawSetPixel(x1 += stepx, y1 += stepy, colour); // o - RawSetPixel(x2, y2 -= stepy, colour); // o - RawSetPixel(x2 -= stepx, y2 -= stepy, colour); // x - d += incr1; - } - else - { - if (d < c) - { - RawSetPixel(x1, y1, colour); // Pattern: - RawSetPixel(x1 += stepx, y1 += stepy, colour); // o - RawSetPixel(x2, y2, colour); // x o - RawSetPixel(x2 -= stepx, y2 -= stepy, colour); // - } - else - { - RawSetPixel(x1, y1 += stepy, colour); // Pattern: - RawSetPixel(x1 += stepx, y1, colour); // o o - RawSetPixel(x2, y2 -= stepy, colour); // x - RawSetPixel(x2 -= stepx, y2, colour); // - } - - d += incr2; - } // else - } // for i - - if (extras > 0) - { - if (d > 0) - { - RawSetPixel(x1 += stepx, y1 += stepy, colour); - if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); - if (extras > 2) RawSetPixel(x2 -= stepx, y2 -= stepy, colour); - } - else - if (d < c) - { - RawSetPixel(x1 += stepx, y1, colour); - if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); - if (extras > 2) RawSetPixel(x2 -= stepx, y2, colour); - } - else - { - - RawSetPixel(x1 += stepx, y1 += stepy, colour); - - if (extras > 1) RawSetPixel(x1 += stepx, y1, colour); - if (extras > 2) - { - if (d > c) - RawSetPixel(x2 -= stepx, y2 -= stepy, colour); - else - RawSetPixel(x2 -= stepx, y2, colour); - } // if extras > 2 - - } // else - } // if extras > 0 - } // else - - } - else - { - - int32 length = (dy - 1) >> 2; - int32 extras = (dy - 1) & 3; - int32 incr2 = (dx << 2) - (dy << 1); - - if (incr2 < 0) - { - int32 c = dx << 1; - int32 incr1 = c << 1; - int32 d = incr1 - dy; - - for (int32 i = 0; i < length; i++) - { - y1 += stepy; - y2 -= stepy; - - if (d < 0) { - RawSetPixel(x1, y1, colour); - RawSetPixel(x1, y1 += stepy, colour); - RawSetPixel(x2, y2, colour); - RawSetPixel(x2, y2 -= stepy, colour); - - d += incr1; - } - else - { - - if (d < c) { - RawSetPixel(x1, y1, colour); - RawSetPixel(x1 += stepx, y1 += stepy, colour); - RawSetPixel(x2, y2, colour); - RawSetPixel(x2 -= stepx, y2 -= stepy, colour); - } else { - RawSetPixel(x1 += stepx, y1, colour); - RawSetPixel(x1, y1 += stepy, colour); - RawSetPixel(x2 -= stepx, y2, colour); - RawSetPixel(x2, y2 -= stepy, colour); - } // else - - d += incr2; - } // else - } // for i - - if (extras > 0) - { - if (d < 0) - { - RawSetPixel(x1, y1 += stepy, colour); - if (extras > 1) RawSetPixel(x1, y1 += stepy, colour); - if (extras > 2) RawSetPixel(x2, y2 -= stepy, colour); - } - else - if (d < c) { - RawSetPixel(x1, y1 += stepy, colour); - if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); - if (extras > 2) RawSetPixel(x2, y2 -= stepy, colour); - } else { - RawSetPixel(x1 += stepx, y1 += stepy, colour); - if (extras > 1) RawSetPixel(x1, y1 += stepy, colour); - if (extras > 2) RawSetPixel(x2 -= stepx, y2 -= stepy, colour); - } // else - } // if extras > 0 - } - else - { - int32 c = (dx - dy) << 1; - int32 incr1 = c << 1; - int32 d = incr1 + dy; - - for (int32 i = 0; i < length; i++) - { - y1 += stepy; - y2 -= stepy; - - if (d > 0) - { - RawSetPixel(x1 += stepx, y1, colour); - RawSetPixel(x1 += stepx, y1 += stepy, colour); - RawSetPixel(x2 -= stepx, y2, colour); - RawSetPixel(x2 -= stepx, y2 -= stepy, colour); - d += incr1; - } - else - { - if (d < c) { - RawSetPixel(x1, y1, colour); - RawSetPixel(x1 += stepx, y1 += stepy, colour); - RawSetPixel(x2, y2, colour); - RawSetPixel(x2 -= stepx, y2 -= stepy, colour); - } else { - RawSetPixel(x1 += stepx, y1, colour); - RawSetPixel(x1, y1 += stepy, colour); - RawSetPixel(x2 -= stepx, y2, colour); - RawSetPixel(x2, y2 -= stepy, colour); - } // else - d += incr2; - } // else - } // for - - if (extras > 0) - { - if (d > 0) - { - RawSetPixel(x1 += stepx, y1 += stepy, colour); - if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); - if (extras > 2) RawSetPixel(x2 -= stepx, y2 -= stepy, colour); - } - else - if (d < c) - { - RawSetPixel(x1, y1 += stepy, colour); - if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); - if (extras > 2) RawSetPixel(x2, y2 -= stepy, colour); - } - else - { - RawSetPixel(x1 += stepx, y1 += stepy, colour); - if (extras > 1) RawSetPixel(x1, y1 += stepy, colour); - if (extras > 2) - { - if (d > c) - RawSetPixel(x2 -= stepx, y2 -= stepy, colour); - else - RawSetPixel(x2, y2 -= stepy, colour); - } // if extras > 2 - } // else - } // if extras > 0 - } // else - } // else -} // void ogSurface::RawLine() - -void ogSurface::RawSetPixel(uInt32 x, uInt32 y, uInt32 colour) -{ - if (ogIsBlending()) - { - uInt8 sR, sG, sB, sA; - uInt8 dR, dG, dB; - ogUnpack(colour, sR, sG, sB, sA); - if (sA == 0) return; - if (sA != 255) - { - uInt32 inverseA = 255 - sA; - ogUnpack(RawGetPixel(x, y), dR, dG, dB); - uInt32 newR = (dR * inverseA + sR * sA) >> 8; - uInt32 newG = (dG * inverseA + sG * sA) >> 8; - uInt32 newB = (dB * inverseA + sB * sA) >> 8; - //mji for gtk colour = ogPack(newR, newG, newB, inverseA); - colour = ogPack(newR, newG, newB, 255); - } - } // if - - void * ptr = reinterpret_cast(buffer + lineOfs[y] + x*bytesPerPix); - setPixel(ptr, colour); -#if 0 - //ptr = static_cast(buffer) + lineOfs[y]; - - switch (bytesPerPix) { - case 4: - _asm { - mov eax, this ; - mov edi, [eax + ogSurface::buffer] ; - mov esi, [eax + ogSurface::lineOfs] ; - mov ebx, [y] ; - mov ecx, [x] ; - - // Calculate offset, prepare the pixel to be drawn - mov edx, [esi + ebx * 4] - nop ; - add edi, edx ; - nop ; - - shl ecx, 2 ; // adjust for pixel size - add edi, ecx ; - - // Draw the pixel - mov eax, [colour] ; - mov [edi], eax ; - }; // asm - break; - case 3: - _asm { - mov eax, this ; - mov edi, [eax + ogSurface::buffer] ; - mov esi, [eax + ogSurface::lineOfs] ; - mov ebx, [y] ; - mov ecx, [x] ; - - // Calculate offset, prepare the pixel to be drawn - mov edx, [esi + ebx * 4] ; - lea ecx, [ecx *2 + ecx] ; - add edi, edx ; - add edi, ecx ; // adjust for pixel size - - // Draw the pixel - mov ax, word ptr [colour] ; - mov bl, byte ptr [colour+2] ; - mov [edi], ax ; - mov [edi+2], bl ; - }; // - break; - case 2: - _asm { - mov eax, this ; - mov edi, [eax + ogSurface::buffer] ; - mov esi, [eax + ogSurface::lineOfs] ; - mov ebx, [y] ; - mov ecx, [x] ; - - // Calculate offset, prepare the pixel to be drawn - mov edx, [esi + ebx * 4] ; - add edi, edx ; - add ecx, ecx ; // adjust for pixel size - mov ax, word ptr [colour] ; - add edi, ecx ; - - // Draw the pixel - mov [edi], ax ; - }; // asm - case 1: - _asm { - mov eax, this ; - mov edi, [eax + ogSurface::buffer] ; - mov esi, [eax + ogSurface::lineOfs] ; - mov ebx, [y] ; - mov ecx, [x] ; - - // Calculate offset, prepare the pixel to be drawn - mov edx, [esi + ebx * 4] ; - nop ; - add edi, edx ; - nop ; - mov al, byte ptr [colour] ; - add edi, ecx ; - - // Draw the pixel - mov [edi], al ; - }; - break; - } // switch -#endif -} // void ogSurface::RawSetPixel() - -void ogSurface::RawSetPixel(uInt32 x, uInt32 y, uInt8 r, uInt8 g, uInt8 b, uInt8 a) -{ - uInt32 newR, newG, newB, inverseA; - uInt8 dR, dG, dB; - uInt32 colour; - - do { - if (ogIsBlending()) { - if (a == 0) return; - if (a == 255) { - colour = ogPack(r, g, b, a); - break; - } // if a == 255 - - inverseA = 255 - a; - ogUnpack(RawGetPixel(x, y), dR, dG, dB); - newR = (dR * inverseA + r * a) >> 8; - newG = (dG * inverseA + g * a) >> 8; - newB = (dB * inverseA + b * a) >> 8; - //mji for gtk colour = ogPack(newR, newG, newB, inverseA); - colour = ogPack(newR, newG, newB, 255); - } else colour = ogPack(r, g, b, a); - } while (false); - - void * ptr = reinterpret_cast(buffer + lineOfs[y] + x*bytesPerPix); - setPixel(ptr, colour); - -} // void ogSurface::RawSetPixel() - - -bool ogSurface::ogAlias(ogSurface& src, uInt32 x1, uInt32 y1, uInt32 x2, uInt32 y2) -{ - uInt32 tmp; - - if (dataState == ogOwner) - { - ogSetLastError(ogAlreadyOwner); - return false; - } // if - - if (x2 < x1) - { - tmp= x2; - x2 = x1; - x1 = tmp; - } // if - - if (y2 < y1) - { - tmp= y2; - y2 = y1; - y1 = tmp; - } // if - - maxX = (x2-x1); - maxY = (y2-y1); - - dataState = ogAliasing; - - bSize = 0; - lSize = 0; - - owner = &src; - buffer =(reinterpret_cast(src.buffer)+x1*(src.bytesPerPix)); - lineOfs=&src.lineOfs[y1]; - attributes = src.attributes; - - pal = src.pal; - xRes = src.xRes; - yRes = src.yRes; - BPP = src.BPP; - bytesPerPix = src.bytesPerPix; - pixFmtID = src.pixFmtID; - - // For 8bpp modes the next part doesn't matter - redFieldPosition = src.redFieldPosition; - greenFieldPosition = src.greenFieldPosition; - blueFieldPosition = src.blueFieldPosition; - alphaFieldPosition = src.alphaFieldPosition; - // The next part is only used by 15/16bpp - redShifter = src.redShifter; - greenShifter = src.greenShifter; - blueShifter = src.blueShifter; - alphaShifter = src.alphaShifter; - - alphaMasker = src.alphaMasker; - - // Use the current pixel functions - setPixel = src.setPixel; - getPixel = src.getPixel; - - return true; -} // bool ogSurface::ogAlias() - -void ogSurface::ogArc(int32 xCenter, int32 yCenter, uInt32 radius, - uInt32 sAngle, uInt32 eAngle, uInt32 colour) -{ - int32 p; - uInt32 x, y, tmp; - double alpha; - - if (radius == 0) - { - ogSetPixel(xCenter, yCenter, colour); - return; - } // if - - sAngle %= 361; - eAngle %= 361; - - if (sAngle > eAngle) { - tmp = sAngle; - sAngle = eAngle; - eAngle = tmp; - } // if - - x = 0; - y = radius; - p = 3-2*radius; - - while (x <= y) - { - alpha = (180.0/3.14159265358979)*atan((double)x/(double)y); - - if ((alpha >= sAngle) && (alpha <= eAngle)) - ogSetPixel(xCenter-x, yCenter-y, colour); - - if ((90-alpha >= sAngle) && (90-alpha <= eAngle)) - ogSetPixel(xCenter-y, yCenter-x, colour); - - if ((90+alpha >= sAngle) && (90+alpha <= eAngle)) - ogSetPixel(xCenter-y, yCenter+x, colour); - - if ((180-alpha >= sAngle) && (180-alpha <= eAngle)) - ogSetPixel(xCenter-x, yCenter+y, colour); - - if ((180+alpha >= sAngle) && (180+alpha <= eAngle)) - ogSetPixel(xCenter+x, yCenter+y, colour); - - if ((270-alpha >= sAngle) && (270-alpha <= eAngle)) - ogSetPixel(xCenter+y, yCenter+x, colour); - - if ((270+alpha >= sAngle) && (270+alpha <= eAngle)) - ogSetPixel(xCenter+y, yCenter-x, colour); - - if ((360-alpha >= sAngle) && (360-alpha <= eAngle)) - ogSetPixel(xCenter+x, yCenter-y, colour); - - if (p < 0) - p += 4*x+6; - else { - p += 4*(x-y)+10; - --y; - } // else - ++x; - } // while -} // void ogSurface::ogArc() - -bool ogSurface::ogAvail() -{ - return ((buffer != NULL) && (lineOfs != NULL)); -} // bool ogSurface::ogAvail() - -void ogSurface::ogBSpline(uInt32 numPoints, ogPoint2d* points, uInt32 segments, uInt32 colour) -{ - if (points == NULL) return; - - auto calculate = ([] (double mu, int32 p0, int32 p1, int32 p2, int32 p3) - { - double mu2, mu3; - mu2 = mu*mu; - mu3 = mu2*mu; - return (int32)(0.5f+(1.0/6.0)*(mu3*(-p0+3.0*p1-3.0*p2+p3)+ - mu2*(3.0*p0-6.0*p1+3.0*p2)+ - mu*(-3.0*p0+3.0*p2)+(p0+4.0*p1+p2))); - }); // calculate - - if ((numPoints < 4) || (numPoints > 255) || (segments == 0)) return; - - double mu, mudelta; - int32 x1, y1, x2, y2; - uInt32 n, h; - mudelta = 1.0/segments; - for (n=3; n= 0) - { - ogSetPixel(xCenter+x, yCenter+y, colour); - ogSetPixel(xCenter+x, yCenter-y, colour); - ogSetPixel(xCenter-x, yCenter+y, colour); - ogSetPixel(xCenter-x, yCenter-y, colour); - - if (d + y > 0) { - --y; - d -= 2*y+1; - } // if - - if (x > d) { - ++x; - d += 2*x+1; - } // if - } // while -} // void ogSurface::ogCircle() - -void ogSurface::ogClear(uInt32 colour) -{ - if (!ogAvail()) return; - - if (ogIsBlending()) - { - uInt8 r, g, b, a; - ogUnpack(colour, r, g, b, a); - if (a == 0) return; - if (a != 255) - { - for (uInt32 yy = 0; yy <= maxY; yy++) - for (uInt32 xx = 0; xx <= maxX; xx++) - RawSetPixel(xx, yy, r, g, b, a); - return; - } // if - } // if blending - - for (uInt32 yy = 0; yy <= maxY; yy++) - for (uInt32 xx = 0; xx <= maxX; xx++) - RawSetPixel(xx, yy, colour); -} // void ogSurface::ogClear() - -void ogSurface::ogClear() -{ - ogClear(ogGetTransparentColor()); -} // void ogSurface::ogClear() - -bool ogSurface::ogClone(ogSurface& src) -{ - ogPixelFmt pixFmt; - - if (src.dataState == ogNone) - { - ogSetLastError(ogNoSurface); - return false; - } // if - - src.ogGetPixFmt(pixFmt); - - if (!ogCreate(src.maxX+1, src.maxY+1, pixFmt)) return false; - - *attributes = *src.attributes; - - ogCopyPalette(src); - ogCopy(src); - return true; -} // bool ogSurface::ogClone() - -void ogSurface::ogCopy(ogSurface& src) -{ - uInt32 pixMap[256]; - uInt32 count, xCount, yCount; - uInt32 xx, yy; - uInt8 r, g, b, a; - void * srcPtr; - - if (!ogAvail()) return; - if (!src.ogAvail()) return; - - xCount = src.maxX+1; - if (xCount > maxX+1) xCount = maxX+1; - yCount = src.maxY+1; - if (yCount > maxY+1) yCount = maxY+1; - - if (ogIsBlending()) - { - - for (yy = 0; yy < yCount; yy++) - for (xx = 0; xx < xCount; xx++) - { - src.ogUnpack(src.RawGetPixel(xx, yy), r, g, b, a); - RawSetPixel(xx, yy, r, g, b, a); - } // for xx - - return; - } // if blending - - if (pixFmtID != src.pixFmtID) - { - if (src.bytesPerPix == 1) - { - for (xx = 0; xx < 256; xx++) - pixMap[xx] = ogPack(src.pal[xx].red, - src.pal[xx].green, - src.pal[xx].blue, - src.pal[xx].alpha); - - for (yy = 0; yy < yCount; yy++) - for (xx = 0; xx < xCount; xx++) - RawSetPixel(xx, yy, pixMap[src.RawGetPixel(xx, yy)]); - - } - else - { // if src.bytesPerPix == 1 - ogPixelFmt srcPixFmt, dstPixFmt; - src.ogGetPixFmt(srcPixFmt); - ogGetPixFmt(dstPixFmt); - ogPixCon pc(srcPixFmt, dstPixFmt); - - for (yy = 0; yy < yCount; yy++) - for (xx = 0; xx < xCount; xx++) - RawSetPixel(xx, yy, pc.ConvPix(src.RawGetPixel(xx, yy))); - - } // else - } - else - { - - xCount *= bytesPerPix; - - for (count = 0; count < yCount; count++) - if ((srcPtr = src.ogGetPtr(0, count)) == NULL) - { - /* - * if we are here then we couldn't get a direct memory pointer - * from the source object. This means that it is not a normal - * "memory" buffer and we have to use the implementation inspecific - * interface. We let the source buffer fill a "temporary" buffer - * and then we copy it to where it needs to go. - */ -#ifdef __UBIXOS_KERNEL__ - srcPtr = kmalloc(xCount); // allocate space -#else - srcPtr = malloc(xCount); // allocate space -#endif - if (srcPtr != NULL) { - src.ogCopyLineFrom(0, count, srcPtr, xCount); - ogCopyLineTo(0, count, srcPtr, xCount); -#ifdef __UBIXOS_KERNEL__ - kfree(srcPtr); -#else - free(srcPtr); -#endif - } // if srcPtr!=NULL - } - else - { - ogCopyLineTo(0, count, srcPtr, xCount); - } - } // else -} // void ogSurface::ogCopy() - - -void ogSurface::ogCopyBuf(int32 dX1, int32 dY1, - ogSurface& src, - int32 sX1, int32 sY1, int32 sX2, int32 sY2) -{ - uInt32 pixMap[256]; - int32 xx, yy, count, xCount, yCount; - uInt8 r, g, b, a; - void *srcPtr; - - ogPixelFmt srcPixFmt, dstPixFmt; - - if (!ogAvail()) return; - if (!src.ogAvail()) return; - - if ((dX1 > (int32)maxX) || (dY1 > (int32)maxY)) return; - - // if any of the source buffer is out of bounds then do nothing - if (( (uInt32)sX1 > src.maxX) || ((uInt32)sX2 > src.maxX) || - ( (uInt32)sY1 > src.maxY) || ((uInt32)sY2 > src.maxY)) return; - - if (sX1 > sX2) - { - int32 xSwap= sX1; - sX1= sX2; - sX2= xSwap; - } // if - - if (sY1 > sY2) - { - int32 ySwap = sY1; - sY1= sY2; - sY2= ySwap; - } // if - - xCount = abs(sX2-sX1)+1; - yCount = abs(sY2-sY1)+1; - - if (dX1+xCount > (int32)maxX+1) xCount = maxX-dX1+1; - if (dY1+yCount > (int32)maxY+1) yCount = maxY-dY1+1; - - if (dX1 < 0) - { - xCount += dX1; - sX1 -= dX1; - dX1 = 0; - } // if - - if (dY1 < 0) - { - yCount += dY1; - sY1 -= dY1; - dY1 = 0; - } // if - - if ((dX1+xCount < 0) || (dY1+yCount < 0)) return; - - if (ogIsBlending()) - { - for (yy = 0; yy < yCount; yy++) - for (xx = 0; xx < xCount; xx++) - { - src.ogUnpack(src.RawGetPixel(sX1+xx, sY1+yy), r, g, b, a); - RawSetPixel(dX1+xx, dY1+yy, r, g, b, a); - } // for xx - return; - } // if IsBlending - - if (pixFmtID != src.pixFmtID) - { - - if (src.bytesPerPix == 1) - { - for (xx = 0; xx < 256; xx++) - pixMap[xx] = ogPack(src.pal[xx].red, - src.pal[xx].green, - src.pal[xx].blue, - src.pal[xx].alpha - ); - - for (yy = 0; yy < yCount; yy++) - for (xx = 0; xx < xCount; xx++) - RawSetPixel(dX1+xx,dY1+yy, pixMap[src.ogGetPixel(sX1+xx,sY1+yy)]); - } - else - { - - src.ogGetPixFmt(srcPixFmt); - ogGetPixFmt(dstPixFmt); - ogPixCon pc(srcPixFmt, dstPixFmt); // allocate the pixel converter - - for (yy = 0; yy < yCount; yy++) - for (xx = 0; xx < xCount; xx++) - RawSetPixel(dX1+xx, dY1+yy, pc.ConvPix(src.RawGetPixel(sX1+xx, sY1+yy))); - - } // else - } - else - { - xCount *= bytesPerPix; - - for (count = 0; count < yCount; count++) - if ((srcPtr = src.ogGetPtr(sX1, sY1+count)) == NULL) - { - // if we are here then we couldn't get a direct memory pointer - // from the source object. This means that it is not a normal - // "memory" buffer and we have to use the implementation inspecific - // interface. We let the source buffer fill a "temporary" buffer - // and then we copy it to where it needs to go. - -#ifdef __UBIXOS_KERNEL__ - srcPtr = kmalloc(xCount); // allocate space -#else - srcPtr = malloc(xCount); // allocate space -#endif - if (srcPtr != NULL) { - src.ogCopyLineFrom(sX1, sY1+count, srcPtr, xCount); - ogCopyLineTo(dX1, dY1+count, srcPtr, xCount); -#ifdef __UBIXOS_KERNEL__ - kfree(srcPtr); -#else - free(srcPtr); -#endif - } // if srcPtr!=NULL - } - else - { - ogCopyLineTo(dX1,dY1+count,srcPtr,xCount); - } - } // else -} // void ogSurface::ogCopyBuf() - -void ogSurface::ogCopyLineTo(uInt32 dx, uInt32 dy, const void * src, uInt32 size) -{ - /* - * CopyLineTo() - * - * Inputs: - * - * dx - Destination X of the target buffer - * dy - Destination Y of the target buffer - * src - buffer to copy - * size - size in bytes *NOT* pixels - * - * Copies a run of pixels (of the same format) to (x,y) of a buffer - * - * This method is required because of the different implementations of - * copying a run of pixels to a buffer - * - * WARNING!!! This does *NO* error checking. It is assumed that you've - * done all of that. CopyLineTo and CopyLineFrom are the only - * methods that don't check to make sure you're hosing things. Don't - * use this method unless YOU KNOW WHAT YOU'RE DOING!!!!!!!!! - */ - - memcpy( buffer+lineOfs[dy]+dx*bytesPerPix, // dest - src, // src - size); // size - -} // ogSurface::ogCopyLineTo - -void ogSurface::ogCopyLineFrom(uInt32 sx, uInt32 sy, void * dst, uInt32 size) -{ - /* - * CopyLineFrom() - * - * Inputs: - * - * sx - Source X of the target buffer - * sy - Source Y of the target buffer - * dest - where to put it - * size - size in bytes *NOT* pixels - * - * Copies a run of pixels (of the same format) to (x,y) of a buffer - * - * This method is required because of the different implementations of - * copying a run of pixels to a buffer - * - * WARNING!!! This does *NO* error checking. It is assumed that you've - * done all of that. CopyLineTo and CopyLineFrom are the only - * methods that don't check to make sure you're hosing things. Don't - * use this method unless YOU KNOW WHAT YOU'RE DOING!!!!!!!!! - */ - - memcpy( dst, // dest - (uInt8*)buffer+lineOfs[sy]+sx*bytesPerPix, // src - size); // size - - return; -} // ogSurface::ogCopyLineFrom - -void ogSurface::ogCopyPalette(ogSurface& src) -{ - if (src.pal == NULL) return; - if (pal == NULL) pal = new ogRGBA8[256]; - if (pal == NULL) return; - src.ogGetPalette(pal); - // memcpy(pal, src.pal, sizeof(ogRGBA8)*256); - return; -} // void ogSurface::ogCopyPalette() - - -bool ogSurface::ogCreate(uInt32 _xRes, uInt32 _yRes, ogPixelFmt _pixFormat) -{ - /* - * ogSurface::ogCreate() - * Allocates memory for a buffer of size _xRes by _yRes with - * the pixel format defined in _pixformat. Allocates memory - * for pal and lineOfs. - */ - uInt8 * newBuffer = NULL; - ptrdiff_t * newLineOfs = NULL; - ogRGBA8 * newPal = NULL; - ogAttribute * newAttributes = NULL; - - uInt32 newBSize; - uInt32 newLSize; - - bool status = false; - - switch (_pixFormat.BPP) { - case 8: - getPixel = ([] (void * ptr) mutable -> uInt32 { return *(reinterpret_cast(ptr)); }); - setPixel = ([] (void * ptr, uInt32 colour) -> void { *(reinterpret_cast(ptr)) = colour; }); - break; - case 15: - case 16: - getPixel = ([] (void * ptr) mutable -> uInt32 { return *(reinterpret_cast(ptr)); }); - setPixel = ([] (void * ptr, uInt32 colour) -> void { *(reinterpret_cast(ptr)) = colour; }); - break; - case 24: - getPixel = ([] (void * ptr) -> uInt32 { - uInt32 colour = 0; - uInt8* src = reinterpret_cast(ptr); - uInt8* dest = reinterpret_cast(&colour); - // This may break depending on endian-ness. TODO: Requires testing. - *dest++ = *src++; - *dest++ = *src++; - *dest++ = *src++; - return colour; - }); // getPixel() 24bpp lambda - setPixel = ([] (void * ptr, uInt32 colour) -> void { - uInt8* src = reinterpret_cast(&colour); - uInt8* dest = reinterpret_cast(ptr); - // This may break depending on endian-ness. TODO: Requires testing. - *dest++ = *src++; - *dest++ = *src++; - *dest++ = *src++; - }); // setPixel() 24bpp lambda - break; - case 32: - getPixel = ([] (void * ptr) -> uInt32 { return *(reinterpret_cast(ptr)); }); - setPixel = ([] (void * ptr, uInt32 colour) -> void { *(reinterpret_cast(ptr)) = colour; }); - break; - default: - ogSetLastError(ogBadBPP); - return false; - } // switch - - newBSize = _xRes * _yRes * ((_pixFormat.BPP + 7) >> 3); - newLSize = _yRes * sizeof(uInt32); // number of scan lines * sizeof(uInt32) - -#ifdef __UBIXOS_KERNEL__ - newBuffer = kmalloc(newBSize); -#else - newBuffer = reinterpret_cast(malloc(newBSize)); -#endif - newLineOfs = new ptrdiff_t[_yRes]; - newPal = new ogRGBA8[256]; - newAttributes = new ogAttribute(); - - do { - - if ((newBuffer == NULL) || - (newLineOfs == NULL) || - (newPal == NULL) || - (newAttributes == NULL)) - { - ogSetLastError(ogMemAllocFail); - break; // break out of do {...} while(false) - } // if - - // check to see if we have already allocated memory .. if so, free it - - if (dataState == ogOwner) { -#ifdef __UBIXOS_KERNEL__ - kfree(buffer); -#else - free((void *)buffer); -#endif - delete [] lineOfs; - delete [] pal; - delete attributes; - } // if dataState - - buffer = newBuffer; - lineOfs = newLineOfs; - pal = newPal; - attributes = newAttributes; - bSize = newBSize; - lSize = newLSize; - - newBuffer = NULL; - newLineOfs = NULL; - newPal = NULL; - newAttributes = NULL; - - BPP = _pixFormat.BPP; - bytesPerPix = (BPP + 7) >> 3; - - ogSetPalette(DEFAULT_PALETTE); - // memcpy(pal, DEFAULT_PALETTE, sizeof(ogRGBA8)*256); - - maxX = _xRes -1; - xRes = _xRes * bytesPerPix; - maxY = _yRes -1; - yRes = _yRes; - - // in the pascal version we go from 1 to maxY .. here we use yy < yRes - // (which is the same) - - lineOfs[0] = 0; - for (size_t yy = 1; yy < yRes; yy++) - lineOfs[yy] = lineOfs[yy-1]+xRes; - - dataState = ogOwner; - - // For 8bpp modes the next part doesn't matter - - redFieldPosition = _pixFormat.redFieldPosition; - greenFieldPosition = _pixFormat.greenFieldPosition; - blueFieldPosition = _pixFormat.blueFieldPosition; - alphaFieldPosition = _pixFormat.alphaFieldPosition; - // The next part is only used by 15/16hpp - redShifter = 8-_pixFormat.redMaskSize; - greenShifter = 8-_pixFormat.greenMaskSize; - blueShifter = 8-_pixFormat.blueMaskSize; - alphaShifter = 8-_pixFormat.alphaMaskSize; - - if (_pixFormat.alphaMaskSize != 0) - alphaMasker = ~(ogPixelFmt::OG_MASKS[_pixFormat.alphaMaskSize] << alphaFieldPosition); - else - alphaMasker = ~0; - - if (bytesPerPix == 1) - { - pixFmtID = 0x08080808; - // turn anti aliasing off by default for 8bpp modes - ogSetAntiAliasing(false); - } - else - { - pixFmtID = (redFieldPosition) | - (greenFieldPosition << 8) | - (blueFieldPosition << 16) | - (alphaFieldPosition << 24); - ogSetAntiAliasing(true); - } // else - - ogClear(ogPack(0, 0, 0)); - - owner = this; - status = true; - } while(false); - -#ifdef __UBIXOS_KERNEL__ - if (newBuffer) kfree(newBuffer); -#else - if (newBuffer) free(newBuffer); -#endif - if (newLineOfs) delete [] newLineOfs; - if (newPal) delete [] newPal; - if (newAttributes) delete newAttributes; - - return status; -} // bool ogSurface::ogCreate() - -void ogSurface::ogCubicBezierCurve(int32 x1, int32 y1, int32 x2, int32 y2, - int32 x3, int32 y3, int32 x4, int32 y4, - uInt32 segments, uInt32 colour) -{ - double tX1, tY1, tX2, tY2, tX3, tY3, mu, mu2, mu3, mudelta; - int32 xStart, yStart, xEnd, yEnd; - uInt32 n; - if (segments < 1) return; - if (segments > 128) segments=128; - - mudelta = 1.0/segments; - mu = mudelta; - tX1 =-x1+3*x2-3*x3+x4; - tY1 =-y1+3*y2-3*y3+y4; - tX2 =3*x1-6*x2+3*x3; - tY2 =3*y1-6*y2+3*y3; - tX3 =-3*x1+3*x2; - tY3 =-3*y1+3*y2; - - xStart = x1; - yStart = y1; - - for (n = 1; n < segments; n++) - { - mu2 = mu*mu; - mu3 = mu2*mu; - xEnd = static_cast(mu3*tX1+mu2*tX2+mu*tX3+x1 +0.5f); - yEnd = static_cast(mu3*tY1+mu2*tY2+mu*tY3+y1 +0.5f); - ogLine(xStart, yStart, xEnd, yEnd, colour); - mu += mudelta; - xStart = xEnd; - yStart = yEnd; - } // for -} // void ogSurface::ogCubicBezierCurve() - -void ogSurface::ogCurve(int32 x1, int32 y1, int32 x2, int32 y2, int32 x3, int32 y3, - uInt32 segments, uInt32 colour) -{ - // This is currently broken. - // ToDo: fix ogCurve - - int64 ex, ey, fx, fy; - int64 t1, t2; - - if (segments<2) segments=2; else if (segments>128) segments=128; - - int64 s = segments; - - x2 = (x2*2)-((x1+x3)/2); - y2 = (y2*2)-((y1+y3)/2); - - ex = (static_cast(x2-x1) << 17) / s; - ey = (static_cast(y2-y1) << 17) / s; - fx = (static_cast(x3-(2*x2)+x1) << 16) / (s*s); - fy = (static_cast(y3-(2*y2)+y1) << 16) / (s*s); - - while (--s > 0) - { - t1 = x3; - t2 = y3; - x3 = (static_cast((fx*segments+ex)*segments) / 65536L)+x1; - y3 = (static_cast((fy*segments+ey)*segments) / 65536L)+y1; - ogLine(static_cast(t1), static_cast(t2), x3, y3, colour); - } // while - - ogLine(x3, y3, x1, y1, colour); - -} // void ogSurface::ogCurve() - - -void ogSurface::ogFillCircle(int32 xCenter, int32 yCenter, uInt32 radius, uInt32 colour) -{ - int32 x, y, d; - x = 0; - y = radius; - d = 4*(1-radius); - - while (y >= 0) - { - if (d + y > 0) - { - ogHLine(xCenter-x, xCenter+x, yCenter-y, colour); - if (y != 0) ogHLine(xCenter-x, xCenter+x, yCenter+y, colour); - - --y; - d -= 4*y+1; - } // if - - - if (x > d) - { - ++x; - d += 4*x+1; - } // if - } // while -} // void ogSurface::ogFillCircle() - -void ogSurface::ogFillGouraudPolygon(uInt32 numPoints, ogPoint2d* polyPoints, ogRGBA8 * colours) -{ - - ogEdgeTable * edges; - int32 currentY = ~0; - - if (numPoints < 3) return; - - edges = new ogEdgeTable(); - - if (edges == NULL) return; // sanity check - - edges->BuildGET_G(numPoints, polyPoints, colours); - - if (edges->globalEdges != NULL) - currentY = edges->globalEdges->startY; - - while ((edges->globalEdges != NULL) || (edges->activeEdges != NULL)) - { - edges->MoveXSortedToAET(currentY); - edges->ScanOutAET_G(*this, currentY); - edges->AdvanceAET(); - edges->XSortAET(); - ++currentY; - if (currentY > (int32)maxY) break; // if we've gone past the bottom, stop - } // while - - delete edges; -} // void ogSurface::ogFillGouraudPolygon() - -void ogSurface::ogFillPolygon(uInt32 numPoints, ogPoint2d* polyPoints, uInt32 colour) -{ - ogEdgeTable * edges; - int32 currentY = ~0; - - if (numPoints < 3) return; - - if (!ogIsBlending()) ogPolygon(numPoints, polyPoints, colour); - - edges = new ogEdgeTable(); - - if (edges == NULL) return; // sanity check - - edges->BuildGET(numPoints, polyPoints); - - if (edges->globalEdges != NULL) - currentY = edges->globalEdges->startY; - - while ((edges->globalEdges != NULL) || (edges->activeEdges != NULL)) - { - edges->MoveXSortedToAET(currentY); - edges->ScanOutAET(*this, currentY, colour); - edges->AdvanceAET(); - edges->XSortAET(); - ++currentY; - if (currentY > (int32)maxY) break; // if we've gone past the bottom, stop - } // while - delete edges; -} // void ogSurface::ogFillPolygon() - - -void ogSurface::ogFillRect(int32 x1, int32 y1, int32 x2, int32 y2, uInt32 colour) -{ - int32 yy, tmp; - - if (x2 < x1) - { - tmp= x2; - x2 = x1; - x1 = tmp; - } // if - - if (y2 < y1) - { - tmp= y2; - y2 = y1; - y1 = tmp; - } // if - - if ((y2 < 0) || (y1 > (int32)maxY)) return; - if (y1 < 0) y1 = 0; - if (y2 > (int32)maxY) y2 = maxY; - for (yy = y1; yy <= y2; yy++) - ogHLine(x1, x2, yy, colour); -} // ogSurface::ogFillRect - -void ogSurface::ogFillTriangle(int32 x1, int32 y1, int32 x2, int32 y2, - int32 x3, int32 y3, uInt32 colour) -{ - ogPoint2d points[3]; - points[0].x = x1; - points[0].y = y1; - points[1].x = x2; - points[1].y = y2; - points[2].x = x3; - points[2].y = y3; - - ogFillPolygon(3, points, colour); - -} // void ogSurface::ogFillTriangle() -uInt32 ogSurface::ogGetAlpha(void) -{ - return (attributes != NULL ? attributes->defaultAlpha : 255L); -} // uInt32 ogSurface::ogGetAlpha() - -uInt32 ogSurface::ogGetColorCount() -{ - if (!ogAvail() || ogGetBytesPerPix() != 1) return 0; - - uInt32 colourCount = 0; - uInt32 colourCounter[256] = {}; - for (uInt32 y = 0; y <= ogGetMaxY(); y++) - { - for (uInt32 x = 0; x <= ogGetMaxX(); x++) - { - colourCounter[ogGetPixel(x, y)]++; - } // for x - } // for y - - for (size_t index = 0; index < std::extent::value; index++) - { - if (colourCounter[index] != 0) colourCount++; - } // for index - - return colourCount; -} // void ogSurface::ogCountColors() - -uInt32 ogSurface::ogGetPixel(int32 x, int32 y) -{ - if (!ogAvail()) return ogGetTransparentColor(); - - if (((uInt32)x > maxX) || ((uInt32)y > maxY)) return ogGetTransparentColor(); - - return RawGetPixel(x, y); -} // uInt32 ogSurface::ogGetPixel() - -void ogSurface::ogGetPalette(ogRGBA8 _pal[256]) -{ - if (pal == NULL) return; - - for (size_t index = 0; index <256; index++) - { - _pal[index].red = pal[index].red; - _pal[index].green = pal[index].green; - _pal[index].blue = pal[index].blue; - _pal[index].alpha = pal[index].alpha; - } // for index -} // void ogSurface::ogGetPalette() - -void ogSurface::ogGetPixFmt(ogPixelFmt& pixfmt) -{ - pixfmt.BPP = BPP; - pixfmt.redFieldPosition = redFieldPosition; - pixfmt.greenFieldPosition = greenFieldPosition; - pixfmt.blueFieldPosition = blueFieldPosition; - pixfmt.alphaFieldPosition = alphaFieldPosition; - pixfmt.redMaskSize = 8-redShifter; - pixfmt.greenMaskSize = 8-greenShifter; - pixfmt.blueMaskSize = 8-blueShifter; - pixfmt.alphaMaskSize = 8-alphaShifter; -} // void ogSurface::ogGetPixFmt() - -void* ogSurface::ogGetPtr(uInt32 x, uInt32 y) -{ - // return (Avail() ? ( (uInt8*)buffer+(lineOfs[y]+x*((BPP+7) >> 3)) ) : NULL ); - return reinterpret_cast(buffer+(lineOfs[y]+x*bytesPerPix)); -} // void* ogSurface::ogGetPtr - -uInt32 ogSurface::ogGetTransparentColor(void) -{ - return (attributes != NULL ? attributes->transparentColor : 0); -} // ogSurface::ogGetTransparentColor - -void ogSurface::ogHFlip(void) -{ - void * tmpBuf1; - void * tmpBuf2; - uInt32 xWidth, count; - - if (!ogAvail()) return; - - xWidth = (maxX+1)*bytesPerPix; - -#ifdef __UBIXOS_KERNEL__ - tmpBuf1 = kmalloc(xWidth); - tmpBuf2 = kmalloc(xWidth); -#else - tmpBuf1 = malloc(xWidth); - tmpBuf2 = malloc(xWidth); -#endif - - if ((tmpBuf1 != NULL) && (tmpBuf2 != NULL)) - { - for (count = 0; count <= (maxY/2); count++) - { - ogCopyLineFrom(0, count, tmpBuf1, xWidth); - ogCopyLineFrom(0, maxY-count,tmpBuf2, xWidth); - ogCopyLineTo(0, maxY-count,tmpBuf1, xWidth); - ogCopyLineTo(0, count, tmpBuf2, xWidth); - } // for count - } -#ifdef __UBIXOS_KERNEL__ - kfree(tmpBuf2); - kfree(tmpBuf1); -#else - free(tmpBuf2); - free(tmpBuf1); -#endif - -} // void ogSurface::ogHFlip() - -void ogSurface::ogHLine(int32 x1, int32 x2, int32 y, uInt32 colour) -{ - int32 tmp; - uInt8 r, g, b, a; - - if (!ogAvail()) return; - if ((uInt32)y > maxY) return; - - if (x1 > x2) - { - tmp= x1; - x1 = x2; - x2 = tmp; - } // if - - if (x1 < 0) x1 = 0; - if (x2 > (int32)maxX) x2 = maxX; - if (x2 < x1) return; - - if (ogIsBlending()) { - ogUnpack(colour, r, g, b, a); - if (a == 0) return; - if (a == 255) { - for (tmp = x1; tmp <= x2; tmp++) - RawSetPixel(tmp, y, r, g, b, a); - return; - } // if a == 255 - } // if blending - for (int32 xx = x1; xx <= x2; xx++) - RawSetPixel(xx, y, colour); - -} // void ogSurface::ogHLine() - -bool ogSurface::ogIsAntiAliasing(void) -{ - return (attributes != NULL ? attributes->antiAlias : false); -} // bool ogSurface::ogIsAntiAliasing() - -bool ogSurface::ogIsBlending(void) -{ - return (attributes != NULL ? attributes->blending : false); -} // bool ogSurface::ogIsBlending() - -void ogSurface::ogLine(int32 x1, int32 y1, int32 x2, int32 y2, uInt32 colour) -{ - if (ClipLine(x1,y1,x2,y2)) - { - if (ogIsAntiAliasing()) - AARawLine(x1, y1, x2, y2, colour); - else - RawLine(x1, y1, x2, y2, colour); - } // if clipLine - return; -} // void ogSurface::ogLine() - -bool ogSurface::ogLoadPalette(const char *palfile) -{ - ogRGBA8 oldPalette[256]; -#ifdef __UBIXOS_KERNEL__ - fileDescriptor *f; - This is possibly incompatible with the kernel. Will need a rewrite. -#endif - bool result; - - if (pal == NULL) - { - pal = new ogRGBA8[256]; - if (pal == NULL) - { - ogSetLastError(ogMemAllocFail); - return false; - } // if - ogSetPalette(DEFAULT_PALETTE); - // memcpy(pal, DEFAULT_PALETTE, sizeof(ogRGBA8)*256); - } // if - - ogGetPalette(oldPalette); - // memcpy(&oldPalette, pal, sizeof(ogRGBA8)*256); - - std::ifstream file; - file.open(palfile, std::ios::in | std::ios::binary); - - if (!file) - { - ogSetLastError(ogFileNotFound); - return false; - } // if !file - - size_t index = 0; - while (index < sizeof(pal) / sizeof(pal[0])) - { - if (!(file >> pal[index].red)) break; - if (!(file >> pal[index].green)) break; - if (!(file >> pal[index].blue)) break; - if (!(file >> pal[index].alpha)) break; - index++; - } - //lresult = fread(pal, sizeof(ogRGBA8), 256, f); - result = (index == 256); - - if (!result) - { - ogSetLastError(ogFileReadError); - ogSetPalette(oldPalette); - // memcpy(pal, &oldPalette, sizeof(ogRGBA8)*256); - } // if - - file.close(); - return result; -} // bool ogSurface::ogLoadPalette() - -void ogSurface::ogOptimize() -{ - if (!ogAvail() || ogGetBytesPerPix() != 1) return; - - int colourCounter[256] = {}; // count of how much that colour is used - size_t swapIndices[256]; // swap indices - size_t reverseIndices[256]; // reverse indices - ogRGBA8 pal[256]; // We also swap the palette entries - - // First acquire a count of all the colours used - for (uInt32 y = 0; y <= ogGetMaxY(); y++) - { - for (uInt32 x = 0; x <= ogGetMaxX(); x++) - { - colourCounter[ogGetPixel(x, y)]++; - } // for x - } // for y - - colourCounter[ogGetTransparentColor()] = INT_MAX; // set 0 so high it's always first - //SortDescending(colourCounter, swapIndices, 256); - - // Sort them in descending order - for (size_t i = 0; i < 256; i++) - swapIndices[i] = i; - - for (size_t k = 1; k < 256; k++) - { - for (size_t i = 0; i <256 - k; i++) - { - if (colourCounter[swapIndices[i]] < colourCounter[swapIndices[i+1]]) - { - size_t temp = swapIndices[i]; - swapIndices[i] = swapIndices[i+1]; - swapIndices[i+1] = temp; - } // if - } // for i - } // for k - - ogGetPalette(pal); - for (size_t i = 0; i < 256; i++) - { - reverseIndices[swapIndices[i]] = i; - //cout << "colourCounter[" << i << "] = " << swapIndices[i] << endl; - // Also swap the palette entries - ogSetPalette(i, pal[swapIndices[i]].red, pal[swapIndices[i]].green, pal[swapIndices[i]].blue); - } // for i - - for (uInt32 y = 0; y <= ogGetMaxY(); y++) - { - for (uInt32 x = 0; x <= ogGetMaxX(); x++) - { - ogSetPixel(x, y, reverseIndices[ogGetPixel(x, y)]); - } // for x - } // for y -} // void ogSurface::ogOptimize() - -uInt32 ogSurface::ogPack(uInt8 red, uInt8 green, uInt8 blue) -{ - uInt32 colour = 0; - - switch (bytesPerPix) { - case 4: - colour = ( (red << redFieldPosition) | - (green << greenFieldPosition) | - (blue << blueFieldPosition) | - (ogGetAlpha() << alphaFieldPosition) ); - break; - case 3: - colour = ( (red << redFieldPosition) | - (green << greenFieldPosition) | - (blue << blueFieldPosition) ); - break; - case 2: - colour = ((red >> redShifter) << redFieldPosition) | - ((green >> greenShifter) << greenFieldPosition) | - ((blue >> blueShifter) << blueFieldPosition) | - ((ogGetAlpha() >> alphaShifter) << alphaFieldPosition); - break; - case 1: - uInt32 dist = 255+255+255; - for (uInt32 idx = 0; idx <= 255; idx++) - { - uInt32 rd = abs(red-pal[idx].red); - uInt32 gd = abs(green-pal[idx].green); - uInt32 bd = abs(blue-pal[idx].blue); - uInt32 newdist = rd + gd + bd; - - if (newdist < dist) - { - dist = newdist; - colour = idx; - } // if - } // for - break; - } // switch - - return colour; - -} // uInt32 ogSurface::ogPack() - -uInt32 ogSurface::ogPack(uInt8 red, uInt8 green, uInt8 blue, uInt8 alpha) -{ - uInt32 colour = 0; - - switch (bytesPerPix) { - case 4: - colour = ( (red << redFieldPosition) | - (green << greenFieldPosition) | - (blue << blueFieldPosition) | - (alpha << alphaFieldPosition) ); - break; - case 3: - colour = ( (red << redFieldPosition) | - (green << greenFieldPosition) | - (blue << blueFieldPosition) ); - break; - case 2: - colour = ((red >> redShifter) << redFieldPosition) | - ((green >> greenShifter) << greenFieldPosition) | - ((blue >> blueShifter) << blueFieldPosition) | - ((alpha >> alphaShifter) << alphaFieldPosition); - break; - case 1: - uInt32 dist = 255+255+255; - for (uInt32 idx = 0; idx <= 255; idx++) - { - uInt32 rd = abs(red-pal[idx].red); - uInt32 gd = abs(green-pal[idx].green); - uInt32 bd = abs(blue-pal[idx].blue); - uInt32 newdist = rd + gd + bd; - - if (newdist < dist) - { - dist = newdist; - colour = idx; - } // if - } // for - break; - } // switch - - return colour; -} // uInt32 ogSurface::ogPack() - -void ogSurface::ogPolygon(uInt32 numPoints, ogPoint2d* polyPoints, uInt32 colour) -{ - if (polyPoints == NULL) return; - - if (numPoints == 1) - { - ogSetPixel(polyPoints[0].x, polyPoints[0].y, colour); - } - else - { - for (size_t count = 0; count < numPoints; count++) - ogLine(polyPoints[count].x, polyPoints[count].y, - polyPoints[(count+1) % numPoints].x, - polyPoints[(count+1) % numPoints].y, - colour); - } -} // void ogSurface::ogPolygon() - -void ogSurface::ogRect(int32 x1, int32 y1, int32 x2, int32 y2, uInt32 colour) -{ - if ((x1 == x2) || (y1 == y2)) - { - - if ((x1 == x2) && (y1 == y2)) - ogSetPixel(x1, y1, colour); - else - ogLine(x1, y1, x2, y2, colour); - - } - else - { - - if (y1 > y2) - { - int32 tmp= y1; - y1 = y2; - y2 = tmp; - } // if - - ogHLine(x1, x2, y1, colour); // Horizline has built in clipping - ogVLine(x1, y1+1, y2-1, colour); // vertline has built in clipping too - ogVLine(x2, y1+1, y2-1, colour); - ogHLine(x1, x2, y2, colour); - - } // else - -} // void ogSurface::ogRect() - -void ogSurface::ogScale(ogSurface& src) { - ogScaleBuf(0, 0, maxX, maxY, src, 0, 0, src.maxX, src.maxY); - return; -} // ogSurface::ogScale - -void ogSurface::ogScaleBuf(int32 dX1, int32 dY1, int32 dX2, int32 dY2, - ogSurface& src, - int32 sX1, int32 sY1, int32 sX2, int32 sY2) -{ - - uInt32 sWidth, dWidth; - uInt32 sHeight, dHeight; - int32 sx, sy, xx, yy; - uInt32 xInc, yInc; - uInt32 origdX1, origdY1; - ogPixelFmt pixFmt; - ogSurface * tmpBuf; - ogSurface * sBuf; - ogSurface * dBuf; - bool doCopyBuf; - - origdX1 = origdY1 = 0; // to keep the compiler from generating a warning - - if (!ogAvail()) return; - if (!src.ogAvail()) return; - - if (sX1 > sX2) - { - xx = sX1; - sX1= sX2; - sX2= xx; - } - - if (sY1 > sY2) - { - yy = sY1; - sY1= sY2; - sY2= yy; - } - - // if any part of the source falls outside the buffer then don't do anything - - if (((uInt32)sX1 > src.maxX) || ((uInt32)sX2 > src.maxX) || - ((uInt32)sY1 > src.maxY) || ((uInt32)sY2 > src.maxY)) return; - - if (dX1 > dX2) - { - xx = dX1; - dX1= dX1; - dX2= xx; - } - - if (dY1 > dY2) - { - yy = dY1; - dY1= dY2; - dY2= yy; - } - - dWidth = (dX2-dX1)+1; - if (dWidth <= 0) return; - - dHeight = (dY2-dY1)+1; - if (dHeight <= 0) return; - - sWidth = (sX2-sX1)+1; - sHeight = (sY2-sY1)+1; - - // convert into 16:16 fixed point ratio - xInc = (sWidth << 16) / dWidth; - yInc = (sHeight << 16) / dHeight; - - if (dX2 > (int32)maxX) - { - xx = (xInc*(dX1-maxX)) >> 16; - sX1 -= xx; - sWidth -= xx; - dWidth -= (dX1-maxX); - dX1 = maxX; - } - - if (dY2 > (int32)maxY) - { - yy = (yInc*(dY2-maxY)) >> 16; - sY2 -= yy; - sHeight -= yy; - dHeight -= (dY2-maxY); - dY2 = maxY; - } - - if (dX1 < 0) - { - xx = (xInc*(-dX1)) >> 16; - sX1 += xx; - sWidth -= xx; - dWidth += dX1; - dX1 = 0; - } - - if (dY1 < 0) - { - yy = (yInc*(-dY1)) >> 16; - sY1 += yy; - sHeight -= yy; - dHeight += dY1; - dY1 = 0; - } - - if ((dWidth <= 0) || (dHeight <= 0)) return; - if ((sWidth <= 0) || (sHeight <= 0)) return; - - // Do a quick check to see if the scale is 1:1 .. in that case just copy - // the image - - if ((dWidth == sWidth) && (dHeight == sHeight)) - { - ogCopyBuf(dX1, dY1, src, sX1, sY1, sX2, sY2); - return; - } - - tmpBuf = NULL; - - /* - * Alright.. this is how we're going to optimize the case of different - * pixel formats. We are going to use copyBuf() to automagically do - * the conversion for us using tmpBuf. Here's how it works: - * If the source buffer is smaller than the dest buffer (ie, we're making - * something bigger) we will convert the source buffer first into the dest - * buffer's pixel format. Then we do the scaling. - * If the source buffer is larger than the dest buffer (ie, we're making - * something smaller) we will scale first and then use copyBuf to do - * the conversion. - * This method puts the onus of conversion on the copyBuf() function which, - * while not excessively fast, does the job. - * The case in which the source and dest are the same size is handled above. - * - */ - if (pixFmtID != src.pixFmtID) - { - - tmpBuf = new ogSurface(); - if (tmpBuf == NULL) return; - if (sWidth*sHeight*src.bytesPerPix <= dWidth*dHeight*bytesPerPix) - { - // if the number of pixels in the source buffer is less than the - // number of pixels in the dest buffer then... - ogGetPixFmt(pixFmt); - if (!tmpBuf->ogCreate(sWidth, sHeight, pixFmt)) return; - tmpBuf->ogCopyPalette(src); - tmpBuf->ogCopyBuf(0, 0, src, sX1, sY1, sX2, sY2); - sX2 -= sX1; - sY2 -= sY1; - sX1 = 0; - sY1 = 0; - sBuf = tmpBuf; - dBuf = this; - doCopyBuf = false; // do we do a copyBuf later? - } - else - { - src.ogGetPixFmt(pixFmt); - if (!tmpBuf->ogCreate(dWidth,dHeight,pixFmt)) return; - tmpBuf->ogCopyPalette(*this); - origdX1 = dX1; - origdY1 = dY1; - dX1 = 0; - dY1 = 0; - dX2 = tmpBuf->maxX; - dY2 = tmpBuf->maxY; - sBuf = &src; - dBuf = tmpBuf; - doCopyBuf = true; - } // else - } - else - { - // pixel formats are identical - sBuf = &src; - dBuf = this; - doCopyBuf = false; - } // else - - sy = sY1 << 16; - - for (yy = dY1; yy <= dY2; yy++) - { - sx = 0; - for (xx = dX1; xx <= dX2; xx++) - { - dBuf->RawSetPixel(xx, yy, - sBuf->RawGetPixel(sX1+(sx >> 16),(sy>>16))); - sx += xInc; - } // for xx - sy += yInc; - } // for yy - - if ((doCopyBuf) && (tmpBuf != NULL)) - ogCopyBuf(origdX1, origdY1, *tmpBuf, 0, 0, tmpBuf->maxX, tmpBuf->maxY); - - delete tmpBuf; -} // void ogSurface::ogScaleBuf() - -uInt32 ogSurface::ogSetAlpha(uInt32 newAlpha) -{ - if (attributes != NULL) - { - uInt32 tmp = attributes->defaultAlpha; - attributes->defaultAlpha = newAlpha; - return tmp; - } - else - { - return newAlpha; - } -} // ogSurface::ogSetAlpha - -bool ogSurface::ogSetAntiAliasing(bool antiAliasing) -{ - if (attributes != NULL) - { - bool previousAA = attributes->antiAlias; - attributes->antiAlias = antiAliasing; - return previousAA; - } - else - { - return antiAliasing; // fail quietly - } -} // bool ogSurface::ogSetAntiAliasing() - -bool ogSurface::ogSetBlending(bool _blending) -{ - bool tmp; - - if (attributes != NULL) { - tmp = attributes->blending; - attributes->blending = _blending; - return tmp; - } else return _blending; - -} // bool ogSurface::ogSetBlending() - -ogErrorCode ogSurface::ogSetLastError(ogErrorCode latestError) -{ - ogErrorCode tmp = lastError; - lastError = latestError; - return tmp; -} // ogErrorCode ogSurface::ogSetLastError() - -void ogSurface::ogSetPalette(const ogRGBA8 newPal[256]) -{ - if (pal == NULL) return; - for (size_t index = 0; index < 256; index++) - { - pal[index].red = newPal[index].red; - pal[index].green = newPal[index].green; - pal[index].blue = newPal[index].blue; - pal[index].alpha = newPal[index].alpha; - } // for index -} // void ogSurface::ogSetPalette() - -void ogSurface::ogSetPalette(uInt8 colour, uInt8 red, uInt8 green, uInt8 blue, uInt8 alpha) -{ - if (pal == NULL) return; - pal[colour].red = red; - pal[colour].green = green; - pal[colour].blue = blue; - pal[colour].alpha = alpha; -} // void ogSurface::ogSetPalette() - -void ogSurface::ogSetPalette(uInt8 colour, uInt8 red, uInt8 green, uInt8 blue) -{ - if (pal == NULL) return; - pal[colour].red = red; - pal[colour].green = green; - pal[colour].blue = blue; - pal[colour].alpha = ogGetAlpha(); -} // void ogSurface::ogSetPalette() - -void ogSurface::ogSetPixel(int32 x, int32 y, uInt32 colour) -{ - if (!ogAvail()) return; - - if (((uInt32)x > maxX) || ((uInt32)y > maxY)) return; - - RawSetPixel(x, y, colour); -} // void ogSurface::ogSetPixel() - -void ogSurface::ogSetPixel(int32 x, int32 y, uInt8 r, uInt8 g, uInt8 b, uInt8 a) { - if (!ogAvail()) return; - - if (((uInt32)x > maxX) || ((uInt32)y > maxY)) return; - - RawSetPixel(x, y, r, g, b, a); -} // void ogSurface::ogSetPixel() - -uInt32 ogSurface::ogSetTransparentColor(uInt32 colour) -{ - uInt32 preColour = 0; - - if (attributes != NULL) - { - preColour = attributes->transparentColor & ogGetAlphaMasker(); - attributes->transparentColor = colour & ogGetAlphaMasker(); - } // if - - return preColour; -} // uInt32 ogSurface::ogSetTransparentColor() - -//static double f(double g) { return g*g*g-g; } - -void ogSurface::ogSpline(uInt32 numPoints, ogPoint2d* points, uInt32 segments, - uInt32 colour) -{ - int32 i, oldY, oldX, x, y, j; - double part, t, xx, yy, tmp; - double * zc; - double * dx; - double * dy; - double * u; - double * wndX1; - double * wndY1; - double * px; - double * py; - - auto f = ([] (double g) -> double { return g*g*g*-g; }); - bool runOnce; - - if ((numPoints < 2) || (points == NULL)) return; - - zc = new double[numPoints]; - dx = new double[numPoints]; - dy = new double[numPoints]; - u = new double[numPoints]; - wndX1 = new double[numPoints]; - wndY1 = new double[numPoints]; - px = new double[numPoints]; - py = new double[numPoints]; - - do { - if (zc == NULL) break; - if (dx == NULL) break; - if (dy == NULL) break; - if (wndX1 == NULL) break; - if (wndY1 == NULL) break; - if (px == NULL) break; - if (py == NULL) break; - - for (i = 0; (uInt32)i < numPoints; i++) - { - zc[i] = dx[i] = dy[i] = u[i] = wndX1[i] = wndY1[i] = px[i] = py[i] = 0.0f; - } - - runOnce = false; - oldX = oldY = 0; - - x = points[0].x; - y = points[0].y; - - for (i = 1; (uInt32)i < numPoints; i++) - { - xx = points[i-1].x - points[i].x; - yy = points[i-1].y - points[i].y; - t = sqrt(xx*xx + yy*yy); - zc[i] = zc[i-1]+t; - } // for - - u[0] = zc[1] - zc[0] +1; - for (i = 1; (uInt32)i < numPoints-1; i++) - { - u[i] = zc[i+1]-zc[i]+1; - tmp = 2*(zc[i+1]-zc[i-1]); - dx[i] = tmp; - dy[i] = tmp; - wndY1[i] = 6.0f*((points[i+1].y-points[i].y)/u[i]- - (points[i].y-points[i-1].y)/u[i-1]); - wndX1[i] = 6.0f*((points[i+1].x-points[i].x)/u[i]- - (points[i].x-points[i-1].x)/u[i-1]); - } // for - - for (i = 1; (uInt32)i < numPoints-2; i++) - { - wndY1[i+1] = wndY1[i+1]-wndY1[i]*u[i]/dy[i]; - dy[i+1] = dy[i+1]-u[i]*u[i]/dy[i]; - wndX1[i+1] = wndX1[i+1]-wndX1[i]*u[i]/dx[i]; - dx[i+1] = dx[i+1]-u[i]*u[i]/dx[i]; - } // for - - for (i = numPoints-2; i > 0; i--) - { - py[i] = (wndY1[i]-u[i]*py[i+1])/dy[i]; - px[i] = (wndX1[i]-u[i]*px[i+1])/dx[i]; - } // for - - for (i = 0; (uInt32)i < numPoints-1; i++) - { - for (j = 0; (uInt32)j <= segments; j++) - { - part = zc[i]-(((zc[i]-zc[i+1])/segments)*j); - t = (part-zc[i])/u[i]; - part = t * points[i+1].y + - (1.0-t)*points[i].y + - u[i] * u[i] * ( f(t) * py[i+1] + f(1.0-t) * py[i]) /6.0; - // y = Round(part); - y = static_cast(part+0.5f); - part = zc[i]-(((zc[i]-zc[i+1])/segments)*j); - t = (part-zc[i])/u[i]; - part = t*points[i+1].x+(1.0-t)*points[i].x+u[i]*u[i]*(f(t)*px[i+1]+ - f(1.0-t)*px[i])/6.0; - - // x = Round(part); - x = static_cast(part+0.5f); - if (runOnce) ogLine(oldX, oldY, x, y, colour); else runOnce = true; - oldX = x; - oldY = y; - } // for j - } // for i - } while (false); - - delete [] py; - delete [] px; - delete [] wndY1; - delete [] wndX1; - delete [] u; - delete [] dy; - delete [] dx; - delete [] zc; - -} // void ogSurface::ogSpline() - -void ogSurface::ogTriangle(int32 x1, int32 y1, int32 x2, int32 y2, int32 x3, int32 y3, uInt32 colour) -{ - ogLine(x1, y1, x2, y2,colour); - ogLine(x2, y2, x3, y3,colour); - ogLine(x3, y3, x1, y1,colour); -} // void ogSurface::ogTriangle() - -void ogSurface::ogUnpack(uInt32 colour, uInt8& red, uInt8& green, uInt8& blue) -{ - switch (bytesPerPix) - { - case 4: - case 3: - red = colour >> redFieldPosition; - green = colour >> greenFieldPosition; - blue = colour >> blueFieldPosition; - break; - case 2: - red = ((colour >> redFieldPosition) << redShifter); - green = ((colour >> greenFieldPosition) << greenShifter); - blue = ((colour >> blueFieldPosition) << blueShifter); - if (red != 0) red += ogPixelFmt::OG_MASKS[redShifter]; - if (green != 0) green += ogPixelFmt::OG_MASKS[greenShifter]; - if (blue != 0) blue += ogPixelFmt::OG_MASKS[blueShifter]; - break; - case 1: - - if (pal == NULL) - { - red = green = blue = 0; - return; - } // if pal == null - - if (colour > 255) colour &= 255; - red = pal[colour].red; - green = pal[colour].green; - blue = pal[colour].blue; - break; - default: - red = 0; - green = 0; - blue = 0; - } // switch - -} // void ogSurface::ogUnpack() - -void ogSurface::ogUnpack(uInt32 colour, uInt8& red, uInt8& green, uInt8& blue, uInt8& alpha) -{ - - switch (bytesPerPix) { - case 4: - red = colour >> redFieldPosition; - green = colour >> greenFieldPosition; - blue = colour >> blueFieldPosition; - alpha = colour >> alphaFieldPosition; - break; - case 3: - red = colour >> redFieldPosition; - green = colour >> greenFieldPosition; - blue = colour >> blueFieldPosition; - alpha = ogGetAlpha(); - break; - case 2: - red = ((colour >> redFieldPosition) << redShifter); - green = ((colour >> greenFieldPosition) << greenShifter); - blue = ((colour >> blueFieldPosition) << blueShifter); - if (red != 0) red += ogPixelFmt::OG_MASKS[redShifter]; - if (green != 0) green += ogPixelFmt::OG_MASKS[greenShifter]; - if (blue != 0) blue += ogPixelFmt::OG_MASKS[blueShifter]; - - if (alphaShifter != 8) { - alpha = (colour >> alphaFieldPosition) << alphaShifter; - if (alpha != 0) alpha += ogPixelFmt::OG_MASKS[alphaShifter]; - } else alpha = ogGetAlpha(); - - break; - case 1: - - if (pal == NULL) - { - red = green = blue = alpha = 0; - return; - } // if pal == null - - if (colour > 255) colour &= 255; - red = pal[colour].red; - green = pal[colour].green; - blue = pal[colour].blue; - alpha = pal[colour].alpha; - break; - default: - red = green = blue = alpha = 0; - } // switch - - return; -} // void ogSurface::ogUnpack() - -void ogSurface::ogVFlip() -{ - if (!ogAvail()) return; - - for (uInt32 yy = 0; yy <= maxY; yy++) - { - for (uInt32 xx = 0; xx < maxX/2; xx++) - { - uInt32 swapColour = RawGetPixel(xx, yy); - RawSetPixel(xx, yy, RawGetPixel(maxX-xx, yy)); - RawSetPixel(maxX-xx, yy, swapColour); - } // for xx - } // for yy -} // void ogSurface::ogVFlip() - -void ogSurface::ogVLine(int32 x, int32 y1, int32 y2, uInt32 colour) -{ - int32 tmp; - uInt8 r, g, b, a; - - if (!ogAvail()) return; - if ((uInt32)x > maxX) return; - - if (y1 > y2) - { - tmp= y1; - y1 = y2; - y2 = tmp; - } // if - - if (y1 < 0) y1 = 0; - if (y2 > (int32)maxY) y2 = maxY; - if (y2 < y1) return; - - if (ogIsBlending()) { - - ogUnpack(colour, r, g, b, a); - - if (a == 0) return; - - if (a != 255) { - for (tmp = y1; tmp <= y2; tmp++) - RawSetPixel(x, tmp, r, g, b, a); - return; - } // if - - } // if blending - for (int32 yy = y1; yy <= y2; yy++) - { - RawSetPixel(x, yy, colour); - } -} // void ogSurface::ogVLine() - -ogSurface::~ogSurface(void) { - - if (dataState == ogOwner) - { - delete [] pal; - delete [] lineOfs; - delete attributes; -#ifdef __UBIXOS_KERNEL__ - kfree(buffer); -#else - free(buffer); -#endif - } // if datastate == ogOwner - - pal = NULL; - lineOfs= NULL; - buffer = NULL; - attributes = NULL; - bSize = 0; - lSize = 0; - dataState = ogNone; - return; -} // ogSurface::~ogSurface \ No newline at end of file +#include +#include +#include +#include +#include + +#include "ogTypes.h" +#include "ogEdgeTable.h" +#include "ogPixCon.h" +#include "ogPixelFmt.h" +#include "objgfx.h" + +const static ogRGBA8 DEFAULT_PALETTE[256] = + {{0, 0, 0, 255}, // 0 + {0, 0, 170, 255}, + {0, 170, 0, 255}, + {0, 170, 170, 255}, // 3 + {170, 0, 0, 255}, + {170, 0, 170, 255}, + {170, 85, 0, 255}, + {170, 170, 170, 255}, // 7 + {85, 85, 85, 255}, + {85, 85, 255, 255}, + {85, 255, 85, 255}, + {85, 255, 255, 255}, // 11 + {255, 85, 85, 255}, + {255, 85, 255, 255}, + {255, 255, 85, 255}, + {255, 255, 255, 255}, //15 + {16, 16, 16, 255}, // 16 + {32, 32, 32, 255}, + {48, 48, 48, 255}, + {64, 64, 64, 255}, + {80, 80, 80, 255}, + {96, 96, 96, 255}, + {112, 112, 112, 255}, + {128, 128, 128, 255}, + {144, 144, 144, 255}, + {160, 160, 160, 255}, + {176, 176, 176, 255}, + {192, 192, 192, 255}, + {208, 208, 208, 255}, + {224, 224, 224, 255}, + {240, 240, 240, 255}, + {255, 255, 255, 255}, //31 + {59, 0, 0, 255}, // 32 + {79, 0, 0, 255}, + {103, 0, 0, 255}, + {123, 0, 0, 255}, + {143, 7, 7, 255}, + {167, 7, 7, 255}, + {187, 11, 11, 255}, + {211, 15, 15, 255}, + {231, 19, 19, 255}, + {255, 27, 27, 255}, + {255, 59, 59, 255}, + {255, 91, 91, 255}, + {255, 119, 119, 255}, + {255, 151, 151, 255}, + {255, 183, 183, 255}, + {255, 215, 215, 255}, + {55, 55, 0, 255}, // 48 + {71, 71, 0, 255}, + {87, 87, 0, 255}, + {103, 103, 7, 255}, + {119, 119, 7, 255}, + {135, 135, 11, 255}, + {155, 155, 19, 255}, + {171, 171, 23, 255}, + {187, 187, 31, 255}, + {203, 203, 35, 255}, + {219, 219, 43, 255}, + {239, 239, 59, 255}, + {255, 255, 63, 255}, + {255, 255, 127, 255}, + {255, 255, 187, 255}, + {255, 255, 255, 255}, + {0, 43, 0, 255}, // 64 + {0, 63, 0, 255}, + {0, 83, 0, 255}, + {0, 103, 0, 255}, + {7, 127, 7, 255}, + {7, 147, 7, 255}, + {11, 167, 11, 255}, + {15, 187, 15, 255}, + {19, 211, 19, 255}, + {27, 231, 27, 255}, + {59, 235, 59, 255}, + {91, 239, 91, 255}, + {127, 239, 127, 255}, + {159, 243, 159, 255}, + {195, 247, 195, 255}, + {231, 251, 231, 255}, + {0, 55, 55, 255}, // 80 + {0, 71, 71, 255}, + {0, 87, 87, 255}, + {7, 103, 103, 255}, + {7, 119, 119, 255}, + {11, 135, 135, 255}, + {19, 155, 155, 255}, + {23, 171, 171, 255}, + {31, 187, 187, 255}, + {35, 203, 203, 255}, + {43, 219, 219, 255}, + {51, 235, 235, 255}, + {63, 255, 255, 255}, + {127, 255, 255, 255}, + {187, 255, 255, 255}, + {255, 255, 255, 255}, + {15, 15, 55, 255}, // 96 + {19, 19, 79, 255}, + {27, 27, 103, 255}, + {31, 31, 127, 255}, + {35, 35, 155, 255}, + {39, 39, 179, 255}, + {43, 43, 203, 255}, + {47, 47, 227, 255}, + {51, 51, 255, 255}, + {71, 71, 255, 255}, + {91, 91, 255, 255}, + {111, 111, 255, 255}, + {131, 131, 255, 255}, + {151, 151, 255, 255}, + {175, 175, 255, 255}, + {195, 195, 255, 255}, + {59, 51, 59, 255}, // 112 + {79, 63, 79, 255}, + {103, 71, 103, 255}, + {123, 75, 123, 255}, + {143, 75, 143, 255}, + {167, 71, 167, 255}, + {187, 67, 187, 255}, + {211, 55, 211, 255}, + {231, 43, 231, 255}, + {255, 27, 255, 255}, + {255, 59, 255, 255}, + {255, 91, 255, 255}, + {255, 119, 255, 255}, + {255, 151, 255, 255}, + {255, 183, 255, 255}, + {255, 215, 255, 255}, + {59, 51, 59, 255}, // 128 + {71, 59, 71, 255}, + {83, 71, 83, 255}, + {95, 83, 95, 255}, + {111, 95, 111, 255}, + {123, 103, 123, 255}, + {135, 115, 135, 255}, + {147, 127, 147, 255}, + {163, 139, 163, 255}, + {175, 151, 175, 255}, + {187, 159, 187, 255}, + {203, 171, 203, 255}, + {215, 183, 215, 255}, + {227, 191, 227, 255}, + {239, 203, 239, 255}, + {255, 215, 255, 255}, + {55, 27, 27, 255}, // 144 + {71, 35, 35, 255}, + {91, 43, 43, 255}, + {107, 55, 55, 255}, + {127, 67, 67, 255}, + {143, 75, 75, 255}, + {163, 87, 87, 255}, + {179, 99, 99, 255}, + {199, 111, 111, 255}, + {203, 127, 127, 255}, + {211, 139, 139, 255}, + {219, 159, 159, 255}, + {223, 175, 175, 255}, + {231, 191, 191, 255}, + {239, 211, 211, 255}, + {247, 231, 231, 255}, + {91, 63, 27, 255}, // 160 + {111, 75, 31, 255}, + {127, 87, 39, 255}, + {147, 103, 43, 255}, + {167, 115, 51, 255}, + {187, 127, 55, 255}, + {207, 139, 63, 255}, + {227, 155, 67, 255}, + {247, 167, 75, 255}, + {247, 175, 95, 255}, + {247, 183, 119, 255}, + {247, 195, 139, 255}, + {247, 203, 159, 255}, + {247, 215, 183, 255}, + {247, 227, 203, 255}, + {251, 239, 227, 255}, + {63, 63, 31, 255}, // 176 + {75, 75, 35, 255}, + {87, 87, 43, 255}, + {99, 99, 51, 255}, + {115, 115, 55, 255}, + {127, 127, 63, 255}, + {139, 139, 67, 255}, + {151, 151, 75, 255}, + {167, 167, 83, 255}, + {175, 175, 95, 255}, + {183, 183, 107, 255}, + {191, 191, 123, 255}, + {203, 203, 139, 255}, + {211, 211, 159, 255}, + {219, 219, 175, 255}, + {231, 231, 195, 255}, + {27, 59, 47, 255}, // 192 + {31, 75, 59, 255}, + {39, 87, 67, 255}, + {47, 103, 79, 255}, + {55, 119, 91, 255}, + {59, 135, 99, 255}, + {67, 151, 111, 255}, + {71, 167, 119, 255}, + {79, 183, 127, 255}, + {87, 199, 139, 255}, + {91, 215, 147, 255}, + {99, 231, 155, 255}, + {127, 235, 183, 255}, + {163, 239, 211, 255}, + {195, 243, 231, 255}, + {231, 251, 247, 255}, + {23, 55, 55, 255}, // 208 + {31, 71, 71, 255}, + {39, 87, 87, 255}, + {47, 103, 103, 255}, + {55, 119, 119, 255}, + {67, 139, 139, 255}, + {75, 155, 155, 255}, + {87, 171, 171, 255}, + {99, 187, 187, 255}, + {111, 203, 203, 255}, + {123, 223, 223, 255}, + {143, 227, 227, 255}, + {163, 231, 231, 255}, + {183, 235, 235, 255}, + {203, 239, 239, 255}, + {227, 247, 247, 255}, + {39, 39, 79, 255}, // 224 + {47, 47, 91, 255}, + {55, 55, 107, 255}, + {63, 63, 123, 255}, + {71, 71, 139, 255}, + {79, 79, 151, 255}, + {87, 87, 167, 255}, + {99, 99, 183, 255}, + {107, 107, 199, 255}, + {123, 123, 203, 255}, + {139, 139, 211, 255}, + {155, 155, 219, 255}, + {171, 171, 223, 255}, + {187, 187, 231, 255}, + {207, 207, 239, 255}, + {227, 227, 247, 255}, + {63, 27, 63, 255}, // 240 + {75, 31, 75, 255}, + {91, 39, 91, 255}, + {103, 47, 103, 255}, + {119, 51, 119, 255}, + {131, 59, 131, 255}, + {147, 67, 147, 255}, + {163, 75, 163, 255}, + {175, 83, 175, 255}, + {191, 91, 191, 255}, + {199, 107, 199, 255}, + {207, 127, 207, 255}, + {215, 147, 215, 255}, + {223, 171, 223, 255}, + {231, 195, 231, 255}, + {243, 219, 243, 255}}; + +const double ogSurface::INTENSITIES[32] = { + 1.0, // 0 + 0.984250984251, // 1 + 0.968245836552, // 2 + 0.951971638233, // 3 + 0.935414346693, // 4 + 0.938558653544, // 5 + 0.901387818866, // 6 + 0.883883476483, // 7 + 0.866025403784, // 8 + 0.847791247891, // 9 + 0.829156197589, // 10 + 0.810092587301, // 11 + 0.790569415042, // 12 + 0.770551750371, // 13 + 0.75, // 14 + 0.728868986856, // 15 + 0.707106781187, // 16 + 0.684653196881, // 17 + 0.661437827766, // 18 + 0.637377439199, // 19 + 0.612372435696, // 20 + 0.586301969978, // 21 + 0.559016994375, // 22 + 0.53033008589, // 23 + 0.5, // 24 + 0.467707173347, // 25 + 0.433012701892, // 26 + 0.395284707521, // 27 + 0.353553390593, // 28 + 0.306186217848, // 29 + 0.25, // 30 + 0.176776695297 // 31 +}; // INTENSITIES[] + +// ogSurface constructor +ogSurface::ogSurface(void) +{ + version = ogVERSION; + + dataState = ogNone; + buffer = NULL; + lineOfs = NULL; + pal = NULL; + attributes = NULL; + xRes = 0; + yRes = 0; + maxX = 0; + maxY = 0; + bSize = 0; + lSize = 0; + BPP = 0; + bytesPerPix = 0; + pixFmtID = 0; + redShifter = 0; + greenShifter= 0; + blueShifter = 0; + alphaShifter= 0; + redFieldPosition = 0; + greenFieldPosition = 0; + blueFieldPosition = 0; + alphaFieldPosition = 0; + alphaMasker = 0; + lastError = ogOK; + + // Set these function pointers to do nothing (but not crash) + // in case somebody actually calls them. + setPixel = ([] (void * ptr, uint32_t p) -> void { }); + getPixel = ([] (void * ptr) -> uint32_t { return 0; }); +} // ogSurface::ogSurface() + + +void ogSurface::AARawLine(uint32_t x1, uInt32 y1, uInt32 x2, uInt32 y2, uInt32 colour) +{ + /* + * aaRawLine + * + * private method + * + * draws an unclipped anti-aliased line from (x1,y1) to (x2,y2) using colour + * + */ + uint32_t erradj, erracc; + uint32_t erracctmp, intshift, wgt, wgtCompMask; + int32 dx, dy, tmp, xDir, i; + uInt8 r, g, b, a; + uint32_t alphas[32]; + bool oldBlending; + + if (y1 > y2) + { + tmp= y1; + y1 = y2; + y2 = tmp; + + tmp= x1; + x1 = x2; + x2 = tmp; + } // if + + dx = (x2-x1); + if (dx >= 0) xDir=1; else { dx = -dx; xDir=-1; } + // dx = abs(dx); + dy = (y2 - y1); + + if (dy == 0) + { + ogHLine(x1, x2, y1, colour); + return; + } + + if (dx == 0) + { + ogVLine(x1, y1, y2, colour); + return; + } + + ogUnpack(colour, r, g, b, a); + if (!ogIsBlending()) a = 255; + + for (i = 0; i < 32; i++) + { + alphas[i] = static_cast(INTENSITIES[i]*a + 0.5f); + } // for + + oldBlending = ogSetBlending(true); + + RawSetPixel(x1, y1, r, g, b, a); + + // this is incomplete.. diagonal lines don't travel through the + // center of pixels exactly + + do { + + if (dx == dy) + { + for (; dy != 0; dy--) + { + x1 += xDir; + ++y1; + RawSetPixel(x1, y1, r, g, b, a); + } // for + break; // pop out to the bottom and restore the old blending state + } // if dx==dy + + erracc = 0; + intshift = 32-5; + wgt = 12; + wgtCompMask = 31; + + if (dy > dx) { + /* y-major. Calculate 32-bit fixed point fractional part of a pixel that + * X advances every time Y advances 1 pixel, truncating the result so that + * we won't overrun the endpoint along the X axis + */ +#ifndef __UBIXOS__ + erradj = ((uInt64) dx << 32) / (uInt64)dy; +#else + asm volatile ( // fixed + " xor %%eax, %%eax \n" + " div %%ecx \n" + : "=a" (erradj) + : "d" (dx), "c" (dy) + ); +#endif + + while (--dy) { + erracctmp = erracc; + erracc += erradj; + if (erracc <= erracctmp) x1 += xDir; + y1++; // y-major so always advance Y + /* the nbits most significant bits of erracc give us the intensity + * weighting for this pixel, and the complement of the weighting for + * the paired pixel. + */ + wgt = erracc >> intshift; + ogSetPixel(x1, y1, r, g, b, alphas[wgt]); + ogSetPixel(x1+xDir, y1, r, g, b, alphas[wgt ^ wgtCompMask]); + } // while + + } else { + + /* x-major line. Calculate 32-bit fixed-point fractional part of a pixel + * that Y advances each time X advances 1 pixel, truncating the result so + * that we won't overrun the endpoint along the X axis. + */ +#ifndef __UBIXOS__ + erradj = ((uInt64)dy << 32) / (uInt64)dx; +#else + asm volatile( // fixed + " xor %%eax, %%eax \n" + " div %%ecx \n" + : "=a" (erradj) + : "d" (dy), "c" (dx) + ); +#endif + // draw all pixels other than the first and last + while (--dx) { + erracctmp = erracc; + erracc += erradj; + if (erracc <= erracctmp) y1++; + x1 += xDir; // x-major so always advance X + /* the nbits most significant bits of erracc give us the intensity + * weighting for this pixel, and the complement of the weighting for + * the paired pixel. + */ + wgt = erracc >> intshift; + ogSetPixel(x1, y1, r, g, b, alphas[wgt]); + ogSetPixel(x1, y1+1, r, g, b, alphas[wgt ^ wgtCompMask]); + } // while + } // else + RawSetPixel(x2, y2, r, g, b, alphas[wgt]); + + } while (false); + + ogSetBlending(oldBlending); +} // void ogSurface::AARawLine() + +bool ogSurface::ClipLine(int32& x1, int32& y1, int32& x2, int32& y2) +{ + /* + * clipLine() + * + * private method + * + * clips a line to (0,0),(maxX,maxY); returns true if + * the line segment is in bounds, false if none of the line segment is + * on the screen. Uses HJI's line clipping algorithm. + */ + + int32 tx1, ty1, tx2, ty2; + int32 outCode; + uint32_t andResult, orResult; + andResult = 15; + orResult = 0; + outCode = 0; + if (x1 < 0) outCode+=8; + if (x1 > (int32)maxX) outCode+=4; + if (y1 < 0) outCode+=2; + if (y1 > (int32)maxY) outCode++; + + andResult &= outCode; + orResult |= outCode; + outCode = 0; + + if (x2 < 0) outCode+=8; + if (x2 > (int32)maxX) outCode+=4; + if (y2 < 0) outCode+=2; + if (y2 > (int32)maxY) outCode++; + + andResult &= outCode; + orResult |= outCode; + + if (andResult > 0) return false; + if (orResult == 0) return true; + + // some clipping is required here. + + tx1 = x1; + ty1 = y1; + tx2 = x2; + ty2 = y2; + + if (x1 < 0) + { + ty1 = (x2*y1-x1*y2) / (x2-x1); + tx1 = 0; + } // if + else + { + if (x2 < 0) + { + ty2 = (x2*y1-x1*y2) / (x2-x1); + tx2 = 0; + } // elseif + } + + if (x1 > (int32)maxX) + { + ty1 = (y1*(x2-maxX)+y2*(maxX-x1)) / (x2-x1); + tx1 = maxX; + } // if + else + { + if (x2 > (int32)maxX) + { + ty2 = (y1*(x2-maxX)+y2*(maxX-x1)) / (x2-x1); + tx2 = maxX; + } // elseif + } + + if (((ty1 < 0) && (ty2 < 0)) || + ((ty1>(int32)maxY) && (ty2>(int32)maxY))) return false; + + if (ty1 < 0) + { + tx1 = (x1*y2-x2*y1) / (y2-y1); + ty1 = 0; + } // if + else + { + if (ty2 < 0) + { + tx2 = (x1*y2-x2*y1) / (y2-y1); + ty2 = 0; + } // elseif + } + + if (ty1 > (int32)maxY) + { + tx1 = (x1*(y2-maxY)+x2*(maxY-y1)) / (y2-y1); + ty1 = maxY; + } // if + else + { + if (ty2 > (int32)maxY) + { + tx2 = (x1*(y2-maxY)+x2*(maxY-y1)) / (y2-y1); + ty2 = maxY; + } // elseif + } + + if (((uint32_t)tx1 > maxX) || ((uInt32)tx2 > maxX)) return false; + + x1 = tx1; + y1 = ty1; + x2 = tx2; + y2 = ty2; + + return true; +} // bool ogSurface::ClipLine() + +uint32_t ogSurface::RawGetPixel(uInt32 x, uInt32 y) +{ + //uInt8* ptr = (uInt8*)buffer + lineOfs[y]; // Pointer to pixel at (0,y). + void * ptr = reinterpret_cast(buffer + lineOfs[y] + x*bytesPerPix); + return getPixel(ptr); +#if 0 + uint32_t result = 0; + uint32_t * buf32; + uInt8 * buf24; + uInt16 * buf16; + uInt8 * buf8; + + switch (bytesPerPix) { + case 4: + buf32 = reinterpret_cast(buffer + lineOfs[y] + x*4); + result = *buf32; + //uint32_t * + // uint32_t * buf = static_cast(buffer + lineOfs[y]) + _asm { + mov eax, this ; + mov edi, x ; + mov ebx, y ; + + shl edi, 2 ; // adjust for pixel size + mov esi, [eax + ogSurface::lineOfs] ; + add edi, [esi + ebx*4] ; + add edi, [eax + ogSurface::buffer] ; + + mov eax, [edi] ; + mov result, eax ; + }; + break; + case 3: + buf24 = (buffer + lineOfs[y] + x); + result = *buf24; + break; + case 2: + buf16 = reinterpret_cast(buffer + lineOfs[y] + x*2); + result = *buf16; + break; + case 1: + buf8 = (buffer + lineOfs[y] + x); + result = *buf8; + break; + } // switch + return result; +#endif +} // uint32_t ogSurface::RawGetPixel() + +// wu's double step line algorithm blatently borrowed from: +// http://www.edepot.com/linewu.html + +void ogSurface::RawLine(uint32_t x1, uInt32 y1, uInt32 x2, uInt32 y2, uInt32 colour) +{ + int32 dy = y2 - y1; + int32 dx = x2 - x1; + int32 stepx, stepy; + + if (dy < 0) { dy = -dy; stepy = -1; } else { stepy = 1; } + if (dx < 0) { dx = -dx; stepx = -1; } else { stepx = 1; } + + RawSetPixel(x1, y1, colour); + RawSetPixel(x2, y2, colour); + + if (dx > dy) + { + int32 length = (dx - 1) >> 2; + int32 extras = (dx - 1) & 3; + int32 incr2 = (dy << 2) - (dx << 1); + + if (incr2 < 0) + { + int32 c = dy << 1; + int32 incr1 = c << 1; + int32 d = incr1 - dx; + + for (int32 i = 0; i < length; i++) + { + x1 += stepx; + x2 -= stepx; + + if (d < 0) + { // Pattern: + RawSetPixel(x1, y1, colour); // + RawSetPixel(x1 += stepx, y1, colour); // x o o + RawSetPixel(x2, y2, colour); // + RawSetPixel(x2 -= stepx, y2, colour); + + d += incr1; + } + else + { + + if (d < c) + { // Pattern: + RawSetPixel(x1, y1, colour); // o + RawSetPixel(x1 += stepx, y1 += stepy, colour); // x o + RawSetPixel(x2, y2, colour); // + RawSetPixel(x2 -= stepx, y2 -= stepy, colour); + } + else + { + RawSetPixel(x1, y1 += stepy, colour); // Pattern: + RawSetPixel(x1 += stepx, y1, colour); // o o + RawSetPixel(x2, y2 -= stepy, colour); // x + RawSetPixel(x2 -= stepx, y2, colour); // + } // else + + d += incr2; + } // else + } // for i + + if (extras > 0) + { + + if (d < 0) + { + RawSetPixel(x1 += stepx, y1, colour); + if (extras > 1) RawSetPixel(x1 += stepx, y1, colour); + if (extras > 2) RawSetPixel(x2 -= stepx, y2, colour); + } + else + if (d < c) { + RawSetPixel(x1 += stepx, y1, colour); + if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); + if (extras > 2) RawSetPixel(x2 -= stepx, y2, colour); + } + else + { + RawSetPixel(x1 += stepx, y1 += stepy, colour); + if (extras > 1) RawSetPixel(x1 += stepx, y1, colour); + if (extras > 2) RawSetPixel(x2 -= stepx, y2 -= stepy, colour); + } + } // if extras > 0 + } + else + { + int32 c = (dy - dx) << 1; + int32 incr1 = c << 1; + int32 d = incr1 + dx; + + for (int32 i = 0; i < length; i++) + { + x1 += stepx; + x2 -= stepx; + + if (d > 0) + { + RawSetPixel(x1, y1 += stepy, colour); // Pattern: + RawSetPixel(x1 += stepx, y1 += stepy, colour); // o + RawSetPixel(x2, y2 -= stepy, colour); // o + RawSetPixel(x2 -= stepx, y2 -= stepy, colour); // x + d += incr1; + } + else + { + if (d < c) + { + RawSetPixel(x1, y1, colour); // Pattern: + RawSetPixel(x1 += stepx, y1 += stepy, colour); // o + RawSetPixel(x2, y2, colour); // x o + RawSetPixel(x2 -= stepx, y2 -= stepy, colour); // + } + else + { + RawSetPixel(x1, y1 += stepy, colour); // Pattern: + RawSetPixel(x1 += stepx, y1, colour); // o o + RawSetPixel(x2, y2 -= stepy, colour); // x + RawSetPixel(x2 -= stepx, y2, colour); // + } + + d += incr2; + } // else + } // for i + + if (extras > 0) + { + if (d > 0) + { + RawSetPixel(x1 += stepx, y1 += stepy, colour); + if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); + if (extras > 2) RawSetPixel(x2 -= stepx, y2 -= stepy, colour); + } + else + if (d < c) + { + RawSetPixel(x1 += stepx, y1, colour); + if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); + if (extras > 2) RawSetPixel(x2 -= stepx, y2, colour); + } + else + { + + RawSetPixel(x1 += stepx, y1 += stepy, colour); + + if (extras > 1) RawSetPixel(x1 += stepx, y1, colour); + if (extras > 2) + { + if (d > c) + RawSetPixel(x2 -= stepx, y2 -= stepy, colour); + else + RawSetPixel(x2 -= stepx, y2, colour); + } // if extras > 2 + + } // else + } // if extras > 0 + } // else + + } + else + { + + int32 length = (dy - 1) >> 2; + int32 extras = (dy - 1) & 3; + int32 incr2 = (dx << 2) - (dy << 1); + + if (incr2 < 0) + { + int32 c = dx << 1; + int32 incr1 = c << 1; + int32 d = incr1 - dy; + + for (int32 i = 0; i < length; i++) + { + y1 += stepy; + y2 -= stepy; + + if (d < 0) { + RawSetPixel(x1, y1, colour); + RawSetPixel(x1, y1 += stepy, colour); + RawSetPixel(x2, y2, colour); + RawSetPixel(x2, y2 -= stepy, colour); + + d += incr1; + } + else + { + + if (d < c) { + RawSetPixel(x1, y1, colour); + RawSetPixel(x1 += stepx, y1 += stepy, colour); + RawSetPixel(x2, y2, colour); + RawSetPixel(x2 -= stepx, y2 -= stepy, colour); + } else { + RawSetPixel(x1 += stepx, y1, colour); + RawSetPixel(x1, y1 += stepy, colour); + RawSetPixel(x2 -= stepx, y2, colour); + RawSetPixel(x2, y2 -= stepy, colour); + } // else + + d += incr2; + } // else + } // for i + + if (extras > 0) + { + if (d < 0) + { + RawSetPixel(x1, y1 += stepy, colour); + if (extras > 1) RawSetPixel(x1, y1 += stepy, colour); + if (extras > 2) RawSetPixel(x2, y2 -= stepy, colour); + } + else + if (d < c) { + RawSetPixel(x1, y1 += stepy, colour); + if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); + if (extras > 2) RawSetPixel(x2, y2 -= stepy, colour); + } else { + RawSetPixel(x1 += stepx, y1 += stepy, colour); + if (extras > 1) RawSetPixel(x1, y1 += stepy, colour); + if (extras > 2) RawSetPixel(x2 -= stepx, y2 -= stepy, colour); + } // else + } // if extras > 0 + } + else + { + int32 c = (dx - dy) << 1; + int32 incr1 = c << 1; + int32 d = incr1 + dy; + + for (int32 i = 0; i < length; i++) + { + y1 += stepy; + y2 -= stepy; + + if (d > 0) + { + RawSetPixel(x1 += stepx, y1, colour); + RawSetPixel(x1 += stepx, y1 += stepy, colour); + RawSetPixel(x2 -= stepx, y2, colour); + RawSetPixel(x2 -= stepx, y2 -= stepy, colour); + d += incr1; + } + else + { + if (d < c) { + RawSetPixel(x1, y1, colour); + RawSetPixel(x1 += stepx, y1 += stepy, colour); + RawSetPixel(x2, y2, colour); + RawSetPixel(x2 -= stepx, y2 -= stepy, colour); + } else { + RawSetPixel(x1 += stepx, y1, colour); + RawSetPixel(x1, y1 += stepy, colour); + RawSetPixel(x2 -= stepx, y2, colour); + RawSetPixel(x2, y2 -= stepy, colour); + } // else + d += incr2; + } // else + } // for + + if (extras > 0) + { + if (d > 0) + { + RawSetPixel(x1 += stepx, y1 += stepy, colour); + if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); + if (extras > 2) RawSetPixel(x2 -= stepx, y2 -= stepy, colour); + } + else + if (d < c) + { + RawSetPixel(x1, y1 += stepy, colour); + if (extras > 1) RawSetPixel(x1 += stepx, y1 += stepy, colour); + if (extras > 2) RawSetPixel(x2, y2 -= stepy, colour); + } + else + { + RawSetPixel(x1 += stepx, y1 += stepy, colour); + if (extras > 1) RawSetPixel(x1, y1 += stepy, colour); + if (extras > 2) + { + if (d > c) + RawSetPixel(x2 -= stepx, y2 -= stepy, colour); + else + RawSetPixel(x2, y2 -= stepy, colour); + } // if extras > 2 + } // else + } // if extras > 0 + } // else + } // else +} // void ogSurface::RawLine() + +void ogSurface::RawSetPixel(uint32_t x, uInt32 y, uInt32 colour) +{ + if (ogIsBlending()) + { + uInt8 sR, sG, sB, sA; + uInt8 dR, dG, dB; + ogUnpack(colour, sR, sG, sB, sA); + if (sA == 0) return; + if (sA != 255) + { + uint32_t inverseA = 255 - sA; + ogUnpack(RawGetPixel(x, y), dR, dG, dB); + uint32_t newR = (dR * inverseA + sR * sA) >> 8; + uint32_t newG = (dG * inverseA + sG * sA) >> 8; + uint32_t newB = (dB * inverseA + sB * sA) >> 8; + //mji for gtk colour = ogPack(newR, newG, newB, inverseA); + colour = ogPack(newR, newG, newB, 255); + } + } // if + + void * ptr = reinterpret_cast(buffer + lineOfs[y] + x*bytesPerPix); + setPixel(ptr, colour); +#if 0 + //ptr = static_cast(buffer) + lineOfs[y]; + + switch (bytesPerPix) { + case 4: + _asm { + mov eax, this ; + mov edi, [eax + ogSurface::buffer] ; + mov esi, [eax + ogSurface::lineOfs] ; + mov ebx, [y] ; + mov ecx, [x] ; + + // Calculate offset, prepare the pixel to be drawn + mov edx, [esi + ebx * 4] + nop ; + add edi, edx ; + nop ; + + shl ecx, 2 ; // adjust for pixel size + add edi, ecx ; + + // Draw the pixel + mov eax, [colour] ; + mov [edi], eax ; + }; // asm + break; + case 3: + _asm { + mov eax, this ; + mov edi, [eax + ogSurface::buffer] ; + mov esi, [eax + ogSurface::lineOfs] ; + mov ebx, [y] ; + mov ecx, [x] ; + + // Calculate offset, prepare the pixel to be drawn + mov edx, [esi + ebx * 4] ; + lea ecx, [ecx *2 + ecx] ; + add edi, edx ; + add edi, ecx ; // adjust for pixel size + + // Draw the pixel + mov ax, word ptr [colour] ; + mov bl, byte ptr [colour+2] ; + mov [edi], ax ; + mov [edi+2], bl ; + }; // + break; + case 2: + _asm { + mov eax, this ; + mov edi, [eax + ogSurface::buffer] ; + mov esi, [eax + ogSurface::lineOfs] ; + mov ebx, [y] ; + mov ecx, [x] ; + + // Calculate offset, prepare the pixel to be drawn + mov edx, [esi + ebx * 4] ; + add edi, edx ; + add ecx, ecx ; // adjust for pixel size + mov ax, word ptr [colour] ; + add edi, ecx ; + + // Draw the pixel + mov [edi], ax ; + }; // asm + case 1: + _asm { + mov eax, this ; + mov edi, [eax + ogSurface::buffer] ; + mov esi, [eax + ogSurface::lineOfs] ; + mov ebx, [y] ; + mov ecx, [x] ; + + // Calculate offset, prepare the pixel to be drawn + mov edx, [esi + ebx * 4] ; + nop ; + add edi, edx ; + nop ; + mov al, byte ptr [colour] ; + add edi, ecx ; + + // Draw the pixel + mov [edi], al ; + }; + break; + } // switch +#endif +} // void ogSurface::RawSetPixel() + +void ogSurface::RawSetPixel(uint32_t x, uInt32 y, uInt8 r, uInt8 g, uInt8 b, uInt8 a) +{ + uint32_t newR, newG, newB, inverseA; + uInt8 dR, dG, dB; + uint32_t colour; + + do { + if (ogIsBlending()) { + if (a == 0) return; + if (a == 255) { + colour = ogPack(r, g, b, a); + break; + } // if a == 255 + + inverseA = 255 - a; + ogUnpack(RawGetPixel(x, y), dR, dG, dB); + newR = (dR * inverseA + r * a) >> 8; + newG = (dG * inverseA + g * a) >> 8; + newB = (dB * inverseA + b * a) >> 8; + //mji for gtk colour = ogPack(newR, newG, newB, inverseA); + colour = ogPack(newR, newG, newB, 255); + } else colour = ogPack(r, g, b, a); + } while (false); + + void * ptr = reinterpret_cast(buffer + lineOfs[y] + x*bytesPerPix); + setPixel(ptr, colour); + +} // void ogSurface::RawSetPixel() + + +bool ogSurface::ogAlias(ogSurface& src, uint32_t x1, uInt32 y1, uInt32 x2, uInt32 y2) +{ + uint32_t tmp; + + if (dataState == ogOwner) + { + ogSetLastError(ogAlreadyOwner); + return false; + } // if + + if (x2 < x1) + { + tmp= x2; + x2 = x1; + x1 = tmp; + } // if + + if (y2 < y1) + { + tmp= y2; + y2 = y1; + y1 = tmp; + } // if + + maxX = (x2-x1); + maxY = (y2-y1); + + dataState = ogAliasing; + + bSize = 0; + lSize = 0; + + owner = &src; + buffer =(reinterpret_cast(src.buffer)+x1*(src.bytesPerPix)); + lineOfs=&src.lineOfs[y1]; + attributes = src.attributes; + + pal = src.pal; + xRes = src.xRes; + yRes = src.yRes; + BPP = src.BPP; + bytesPerPix = src.bytesPerPix; + pixFmtID = src.pixFmtID; + + // For 8bpp modes the next part doesn't matter + redFieldPosition = src.redFieldPosition; + greenFieldPosition = src.greenFieldPosition; + blueFieldPosition = src.blueFieldPosition; + alphaFieldPosition = src.alphaFieldPosition; + // The next part is only used by 15/16bpp + redShifter = src.redShifter; + greenShifter = src.greenShifter; + blueShifter = src.blueShifter; + alphaShifter = src.alphaShifter; + + alphaMasker = src.alphaMasker; + + // Use the current pixel functions + setPixel = src.setPixel; + getPixel = src.getPixel; + + return true; +} // bool ogSurface::ogAlias() + +void ogSurface::ogArc(int32 xCenter, int32 yCenter, uint32_t radius, + uint32_t sAngle, uInt32 eAngle, uInt32 colour) +{ + int32 p; + uint32_t x, y, tmp; + double alpha; + + if (radius == 0) + { + ogSetPixel(xCenter, yCenter, colour); + return; + } // if + + sAngle %= 361; + eAngle %= 361; + + if (sAngle > eAngle) { + tmp = sAngle; + sAngle = eAngle; + eAngle = tmp; + } // if + + x = 0; + y = radius; + p = 3-2*radius; + + while (x <= y) + { + alpha = (180.0/3.14159265358979)*atan((double)x/(double)y); + + if ((alpha >= sAngle) && (alpha <= eAngle)) + ogSetPixel(xCenter-x, yCenter-y, colour); + + if ((90-alpha >= sAngle) && (90-alpha <= eAngle)) + ogSetPixel(xCenter-y, yCenter-x, colour); + + if ((90+alpha >= sAngle) && (90+alpha <= eAngle)) + ogSetPixel(xCenter-y, yCenter+x, colour); + + if ((180-alpha >= sAngle) && (180-alpha <= eAngle)) + ogSetPixel(xCenter-x, yCenter+y, colour); + + if ((180+alpha >= sAngle) && (180+alpha <= eAngle)) + ogSetPixel(xCenter+x, yCenter+y, colour); + + if ((270-alpha >= sAngle) && (270-alpha <= eAngle)) + ogSetPixel(xCenter+y, yCenter+x, colour); + + if ((270+alpha >= sAngle) && (270+alpha <= eAngle)) + ogSetPixel(xCenter+y, yCenter-x, colour); + + if ((360-alpha >= sAngle) && (360-alpha <= eAngle)) + ogSetPixel(xCenter+x, yCenter-y, colour); + + if (p < 0) + p += 4*x+6; + else { + p += 4*(x-y)+10; + --y; + } // else + ++x; + } // while +} // void ogSurface::ogArc() + +bool ogSurface::ogAvail() +{ + return ((buffer != NULL) && (lineOfs != NULL)); +} // bool ogSurface::ogAvail() + +void ogSurface::ogBSpline(uint32_t numPoints, ogPoint2d* points, uInt32 segments, uInt32 colour) +{ + if (points == NULL) return; + + auto calculate = ([] (double mu, int32 p0, int32 p1, int32 p2, int32 p3) + { + double mu2, mu3; + mu2 = mu*mu; + mu3 = mu2*mu; + return (int32)(0.5f+(1.0/6.0)*(mu3*(-p0+3.0*p1-3.0*p2+p3)+ + mu2*(3.0*p0-6.0*p1+3.0*p2)+ + mu*(-3.0*p0+3.0*p2)+(p0+4.0*p1+p2))); + }); // calculate + + if ((numPoints < 4) || (numPoints > 255) || (segments == 0)) return; + + double mu, mudelta; + int32 x1, y1, x2, y2; + uint32_t n, h; + mudelta = 1.0/segments; + for (n=3; n= 0) + { + ogSetPixel(xCenter+x, yCenter+y, colour); + ogSetPixel(xCenter+x, yCenter-y, colour); + ogSetPixel(xCenter-x, yCenter+y, colour); + ogSetPixel(xCenter-x, yCenter-y, colour); + + if (d + y > 0) { + --y; + d -= 2*y+1; + } // if + + if (x > d) { + ++x; + d += 2*x+1; + } // if + } // while +} // void ogSurface::ogCircle() + +void ogSurface::ogClear(uint32_t colour) +{ + if (!ogAvail()) return; + + if (ogIsBlending()) + { + uInt8 r, g, b, a; + ogUnpack(colour, r, g, b, a); + if (a == 0) return; + if (a != 255) + { + for (uint32_t yy = 0; yy <= maxY; yy++) + for (uint32_t xx = 0; xx <= maxX; xx++) + RawSetPixel(xx, yy, r, g, b, a); + return; + } // if + } // if blending + + for (uint32_t yy = 0; yy <= maxY; yy++) + for (uint32_t xx = 0; xx <= maxX; xx++) + RawSetPixel(xx, yy, colour); +} // void ogSurface::ogClear() + +void ogSurface::ogClear() +{ + ogClear(ogGetTransparentColor()); +} // void ogSurface::ogClear() + +bool ogSurface::ogClone(ogSurface& src) +{ + ogPixelFmt pixFmt; + + if (src.dataState == ogNone) + { + ogSetLastError(ogNoSurface); + return false; + } // if + + src.ogGetPixFmt(pixFmt); + + if (!ogCreate(src.maxX+1, src.maxY+1, pixFmt)) return false; + + *attributes = *src.attributes; + + ogCopyPalette(src); + ogCopy(src); + return true; +} // bool ogSurface::ogClone() + +void ogSurface::ogCopy(ogSurface& src) +{ + uint32_t pixMap[256]; + uint32_t count, xCount, yCount; + uint32_t xx, yy; + uInt8 r, g, b, a; + void * srcPtr; + + if (!ogAvail()) return; + if (!src.ogAvail()) return; + + xCount = src.maxX+1; + if (xCount > maxX+1) xCount = maxX+1; + yCount = src.maxY+1; + if (yCount > maxY+1) yCount = maxY+1; + + if (ogIsBlending()) + { + + for (yy = 0; yy < yCount; yy++) + for (xx = 0; xx < xCount; xx++) + { + src.ogUnpack(src.RawGetPixel(xx, yy), r, g, b, a); + RawSetPixel(xx, yy, r, g, b, a); + } // for xx + + return; + } // if blending + + if (pixFmtID != src.pixFmtID) + { + if (src.bytesPerPix == 1) + { + for (xx = 0; xx < 256; xx++) + pixMap[xx] = ogPack(src.pal[xx].red, + src.pal[xx].green, + src.pal[xx].blue, + src.pal[xx].alpha); + + for (yy = 0; yy < yCount; yy++) + for (xx = 0; xx < xCount; xx++) + RawSetPixel(xx, yy, pixMap[src.RawGetPixel(xx, yy)]); + + } + else + { // if src.bytesPerPix == 1 + ogPixelFmt srcPixFmt, dstPixFmt; + src.ogGetPixFmt(srcPixFmt); + ogGetPixFmt(dstPixFmt); + ogPixCon pc(srcPixFmt, dstPixFmt); + + for (yy = 0; yy < yCount; yy++) + for (xx = 0; xx < xCount; xx++) + RawSetPixel(xx, yy, pc.ConvPix(src.RawGetPixel(xx, yy))); + + } // else + } + else + { + + xCount *= bytesPerPix; + + for (count = 0; count < yCount; count++) + if ((srcPtr = src.ogGetPtr(0, count)) == NULL) + { + /* + * if we are here then we couldn't get a direct memory pointer + * from the source object. This means that it is not a normal + * "memory" buffer and we have to use the implementation inspecific + * interface. We let the source buffer fill a "temporary" buffer + * and then we copy it to where it needs to go. + */ +#ifdef __UBIXOS_KERNEL__ + srcPtr = kmalloc(xCount); // allocate space +#else + srcPtr = malloc(xCount); // allocate space +#endif + if (srcPtr != NULL) { + src.ogCopyLineFrom(0, count, srcPtr, xCount); + ogCopyLineTo(0, count, srcPtr, xCount); +#ifdef __UBIXOS_KERNEL__ + kfree(srcPtr); +#else + free(srcPtr); +#endif + } // if srcPtr!=NULL + } + else + { + ogCopyLineTo(0, count, srcPtr, xCount); + } + } // else +} // void ogSurface::ogCopy() + + +void ogSurface::ogCopyBuf(int32 dX1, int32 dY1, + ogSurface& src, + int32 sX1, int32 sY1, int32 sX2, int32 sY2) +{ + uint32_t pixMap[256]; + int32 xx, yy, count, xCount, yCount; + uInt8 r, g, b, a; + void *srcPtr; + + ogPixelFmt srcPixFmt, dstPixFmt; + + if (!ogAvail()) return; + if (!src.ogAvail()) return; + + if ((dX1 > (int32)maxX) || (dY1 > (int32)maxY)) return; + + // if any of the source buffer is out of bounds then do nothing + if (( (uint32_t)sX1 > src.maxX) || ((uInt32)sX2 > src.maxX) || + ( (uint32_t)sY1 > src.maxY) || ((uInt32)sY2 > src.maxY)) return; + + if (sX1 > sX2) + { + int32 xSwap= sX1; + sX1= sX2; + sX2= xSwap; + } // if + + if (sY1 > sY2) + { + int32 ySwap = sY1; + sY1= sY2; + sY2= ySwap; + } // if + + xCount = abs(sX2-sX1)+1; + yCount = abs(sY2-sY1)+1; + + if (dX1+xCount > (int32)maxX+1) xCount = maxX-dX1+1; + if (dY1+yCount > (int32)maxY+1) yCount = maxY-dY1+1; + + if (dX1 < 0) + { + xCount += dX1; + sX1 -= dX1; + dX1 = 0; + } // if + + if (dY1 < 0) + { + yCount += dY1; + sY1 -= dY1; + dY1 = 0; + } // if + + if ((dX1+xCount < 0) || (dY1+yCount < 0)) return; + + if (ogIsBlending()) + { + for (yy = 0; yy < yCount; yy++) + for (xx = 0; xx < xCount; xx++) + { + src.ogUnpack(src.RawGetPixel(sX1+xx, sY1+yy), r, g, b, a); + RawSetPixel(dX1+xx, dY1+yy, r, g, b, a); + } // for xx + return; + } // if IsBlending + + if (pixFmtID != src.pixFmtID) + { + + if (src.bytesPerPix == 1) + { + for (xx = 0; xx < 256; xx++) + pixMap[xx] = ogPack(src.pal[xx].red, + src.pal[xx].green, + src.pal[xx].blue, + src.pal[xx].alpha + ); + + for (yy = 0; yy < yCount; yy++) + for (xx = 0; xx < xCount; xx++) + RawSetPixel(dX1+xx,dY1+yy, pixMap[src.ogGetPixel(sX1+xx,sY1+yy)]); + } + else + { + + src.ogGetPixFmt(srcPixFmt); + ogGetPixFmt(dstPixFmt); + ogPixCon pc(srcPixFmt, dstPixFmt); // allocate the pixel converter + + for (yy = 0; yy < yCount; yy++) + for (xx = 0; xx < xCount; xx++) + RawSetPixel(dX1+xx, dY1+yy, pc.ConvPix(src.RawGetPixel(sX1+xx, sY1+yy))); + + } // else + } + else + { + xCount *= bytesPerPix; + + for (count = 0; count < yCount; count++) + if ((srcPtr = src.ogGetPtr(sX1, sY1+count)) == NULL) + { + // if we are here then we couldn't get a direct memory pointer + // from the source object. This means that it is not a normal + // "memory" buffer and we have to use the implementation inspecific + // interface. We let the source buffer fill a "temporary" buffer + // and then we copy it to where it needs to go. + +#ifdef __UBIXOS_KERNEL__ + srcPtr = kmalloc(xCount); // allocate space +#else + srcPtr = malloc(xCount); // allocate space +#endif + if (srcPtr != NULL) { + src.ogCopyLineFrom(sX1, sY1+count, srcPtr, xCount); + ogCopyLineTo(dX1, dY1+count, srcPtr, xCount); +#ifdef __UBIXOS_KERNEL__ + kfree(srcPtr); +#else + free(srcPtr); +#endif + } // if srcPtr!=NULL + } + else + { + ogCopyLineTo(dX1,dY1+count,srcPtr,xCount); + } + } // else +} // void ogSurface::ogCopyBuf() + +void ogSurface::ogCopyLineTo(uint32_t dx, uInt32 dy, const void * src, uInt32 size) +{ + /* + * CopyLineTo() + * + * Inputs: + * + * dx - Destination X of the target buffer + * dy - Destination Y of the target buffer + * src - buffer to copy + * size - size in bytes *NOT* pixels + * + * Copies a run of pixels (of the same format) to (x,y) of a buffer + * + * This method is required because of the different implementations of + * copying a run of pixels to a buffer + * + * WARNING!!! This does *NO* error checking. It is assumed that you've + * done all of that. CopyLineTo and CopyLineFrom are the only + * methods that don't check to make sure you're hosing things. Don't + * use this method unless YOU KNOW WHAT YOU'RE DOING!!!!!!!!! + */ + + memcpy( buffer+lineOfs[dy]+dx*bytesPerPix, // dest + src, // src + size); // size + +} // ogSurface::ogCopyLineTo + +void ogSurface::ogCopyLineFrom(uint32_t sx, uInt32 sy, void * dst, uInt32 size) +{ + /* + * CopyLineFrom() + * + * Inputs: + * + * sx - Source X of the target buffer + * sy - Source Y of the target buffer + * dest - where to put it + * size - size in bytes *NOT* pixels + * + * Copies a run of pixels (of the same format) to (x,y) of a buffer + * + * This method is required because of the different implementations of + * copying a run of pixels to a buffer + * + * WARNING!!! This does *NO* error checking. It is assumed that you've + * done all of that. CopyLineTo and CopyLineFrom are the only + * methods that don't check to make sure you're hosing things. Don't + * use this method unless YOU KNOW WHAT YOU'RE DOING!!!!!!!!! + */ + + memcpy( dst, // dest + (uInt8*)buffer+lineOfs[sy]+sx*bytesPerPix, // src + size); // size + + return; +} // ogSurface::ogCopyLineFrom + +void ogSurface::ogCopyPalette(ogSurface& src) +{ + if (src.pal == NULL) return; + if (pal == NULL) pal = new ogRGBA8[256]; + if (pal == NULL) return; + src.ogGetPalette(pal); + // memcpy(pal, src.pal, sizeof(ogRGBA8)*256); + return; +} // void ogSurface::ogCopyPalette() + + +bool ogSurface::ogCreate(uint32_t _xRes, uInt32 _yRes, ogPixelFmt _pixFormat) +{ + /* + * ogSurface::ogCreate() + * Allocates memory for a buffer of size _xRes by _yRes with + * the pixel format defined in _pixformat. Allocates memory + * for pal and lineOfs. + */ + uInt8 * newBuffer = NULL; + ptrdiff_t * newLineOfs = NULL; + ogRGBA8 * newPal = NULL; + ogAttribute * newAttributes = NULL; + + uint32_t newBSize; + uint32_t newLSize; + + bool status = false; + + switch (_pixFormat.BPP) { + case 8: + getPixel = ([] (void * ptr) mutable -> uint32_t { return *(reinterpret_cast(ptr)); }); + setPixel = ([] (void * ptr, uint32_t colour) -> void { *(reinterpret_cast(ptr)) = colour; }); + break; + case 15: + case 16: + getPixel = ([] (void * ptr) mutable -> uint32_t { return *(reinterpret_cast(ptr)); }); + setPixel = ([] (void * ptr, uint32_t colour) -> void { *(reinterpret_cast(ptr)) = colour; }); + break; + case 24: + getPixel = ([] (void * ptr) -> uint32_t { + uint32_t colour = 0; + uInt8* src = reinterpret_cast(ptr); + uInt8* dest = reinterpret_cast(&colour); + // This may break depending on endian-ness. TODO: Requires testing. + *dest++ = *src++; + *dest++ = *src++; + *dest++ = *src++; + return colour; + }); // getPixel() 24bpp lambda + setPixel = ([] (void * ptr, uint32_t colour) -> void { + uInt8* src = reinterpret_cast(&colour); + uInt8* dest = reinterpret_cast(ptr); + // This may break depending on endian-ness. TODO: Requires testing. + *dest++ = *src++; + *dest++ = *src++; + *dest++ = *src++; + }); // setPixel() 24bpp lambda + break; + case 32: + getPixel = ([] (void * ptr) -> uint32_t { return *(reinterpret_cast(ptr)); }); + setPixel = ([] (void * ptr, uint32_t colour) -> void { *(reinterpret_cast(ptr)) = colour; }); + break; + default: + ogSetLastError(ogBadBPP); + return false; + } // switch + + newBSize = _xRes * _yRes * ((_pixFormat.BPP + 7) >> 3); + newLSize = _yRes * sizeof(uint32_t); // number of scan lines * sizeof(uInt32) + +#ifdef __UBIXOS_KERNEL__ + newBuffer = kmalloc(newBSize); +#else + newBuffer = reinterpret_cast(malloc(newBSize)); +#endif + newLineOfs = new ptrdiff_t[_yRes]; + newPal = new ogRGBA8[256]; + newAttributes = new ogAttribute(); + + do { + + if ((newBuffer == NULL) || + (newLineOfs == NULL) || + (newPal == NULL) || + (newAttributes == NULL)) + { + ogSetLastError(ogMemAllocFail); + break; // break out of do {...} while(false) + } // if + + // check to see if we have already allocated memory .. if so, free it + + if (dataState == ogOwner) { +#ifdef __UBIXOS_KERNEL__ + kfree(buffer); +#else + free((void *)buffer); +#endif + delete [] lineOfs; + delete [] pal; + delete attributes; + } // if dataState + + buffer = newBuffer; + lineOfs = newLineOfs; + pal = newPal; + attributes = newAttributes; + bSize = newBSize; + lSize = newLSize; + + newBuffer = NULL; + newLineOfs = NULL; + newPal = NULL; + newAttributes = NULL; + + BPP = _pixFormat.BPP; + bytesPerPix = (BPP + 7) >> 3; + + ogSetPalette(DEFAULT_PALETTE); + // memcpy(pal, DEFAULT_PALETTE, sizeof(ogRGBA8)*256); + + maxX = _xRes -1; + xRes = _xRes * bytesPerPix; + maxY = _yRes -1; + yRes = _yRes; + + // in the pascal version we go from 1 to maxY .. here we use yy < yRes + // (which is the same) + + lineOfs[0] = 0; + for (size_t yy = 1; yy < yRes; yy++) + lineOfs[yy] = lineOfs[yy-1]+xRes; + + dataState = ogOwner; + + // For 8bpp modes the next part doesn't matter + + redFieldPosition = _pixFormat.redFieldPosition; + greenFieldPosition = _pixFormat.greenFieldPosition; + blueFieldPosition = _pixFormat.blueFieldPosition; + alphaFieldPosition = _pixFormat.alphaFieldPosition; + // The next part is only used by 15/16hpp + redShifter = 8-_pixFormat.redMaskSize; + greenShifter = 8-_pixFormat.greenMaskSize; + blueShifter = 8-_pixFormat.blueMaskSize; + alphaShifter = 8-_pixFormat.alphaMaskSize; + + if (_pixFormat.alphaMaskSize != 0) + alphaMasker = ~(ogPixelFmt::OG_MASKS[_pixFormat.alphaMaskSize] << alphaFieldPosition); + else + alphaMasker = ~0; + + if (bytesPerPix == 1) + { + pixFmtID = 0x08080808; + // turn anti aliasing off by default for 8bpp modes + ogSetAntiAliasing(false); + } + else + { + pixFmtID = (redFieldPosition) | + (greenFieldPosition << 8) | + (blueFieldPosition << 16) | + (alphaFieldPosition << 24); + ogSetAntiAliasing(true); + } // else + + ogClear(ogPack(0, 0, 0)); + + owner = this; + status = true; + } while(false); + +#ifdef __UBIXOS_KERNEL__ + if (newBuffer) kfree(newBuffer); +#else + if (newBuffer) free(newBuffer); +#endif + if (newLineOfs) delete [] newLineOfs; + if (newPal) delete [] newPal; + if (newAttributes) delete newAttributes; + + return status; +} // bool ogSurface::ogCreate() + +void ogSurface::ogCubicBezierCurve(int32 x1, int32 y1, int32 x2, int32 y2, + int32 x3, int32 y3, int32 x4, int32 y4, + uint32_t segments, uInt32 colour) +{ + double tX1, tY1, tX2, tY2, tX3, tY3, mu, mu2, mu3, mudelta; + int32 xStart, yStart, xEnd, yEnd; + uint32_t n; + if (segments < 1) return; + if (segments > 128) segments=128; + + mudelta = 1.0/segments; + mu = mudelta; + tX1 =-x1+3*x2-3*x3+x4; + tY1 =-y1+3*y2-3*y3+y4; + tX2 =3*x1-6*x2+3*x3; + tY2 =3*y1-6*y2+3*y3; + tX3 =-3*x1+3*x2; + tY3 =-3*y1+3*y2; + + xStart = x1; + yStart = y1; + + for (n = 1; n < segments; n++) + { + mu2 = mu*mu; + mu3 = mu2*mu; + xEnd = static_cast(mu3*tX1+mu2*tX2+mu*tX3+x1 +0.5f); + yEnd = static_cast(mu3*tY1+mu2*tY2+mu*tY3+y1 +0.5f); + ogLine(xStart, yStart, xEnd, yEnd, colour); + mu += mudelta; + xStart = xEnd; + yStart = yEnd; + } // for +} // void ogSurface::ogCubicBezierCurve() + +void ogSurface::ogCurve(int32 x1, int32 y1, int32 x2, int32 y2, int32 x3, int32 y3, + uint32_t segments, uInt32 colour) +{ + // This is currently broken. + // ToDo: fix ogCurve + + int64 ex, ey, fx, fy; + int64 t1, t2; + + if (segments<2) segments=2; else if (segments>128) segments=128; + + int64 s = segments; + + x2 = (x2*2)-((x1+x3)/2); + y2 = (y2*2)-((y1+y3)/2); + + ex = (static_cast(x2-x1) << 17) / s; + ey = (static_cast(y2-y1) << 17) / s; + fx = (static_cast(x3-(2*x2)+x1) << 16) / (s*s); + fy = (static_cast(y3-(2*y2)+y1) << 16) / (s*s); + + while (--s > 0) + { + t1 = x3; + t2 = y3; + x3 = (static_cast((fx*segments+ex)*segments) / 65536L)+x1; + y3 = (static_cast((fy*segments+ey)*segments) / 65536L)+y1; + ogLine(static_cast(t1), static_cast(t2), x3, y3, colour); + } // while + + ogLine(x3, y3, x1, y1, colour); + +} // void ogSurface::ogCurve() + + +void ogSurface::ogFillCircle(int32 xCenter, int32 yCenter, uint32_t radius, uInt32 colour) +{ + int32 x, y, d; + x = 0; + y = radius; + d = 4*(1-radius); + + while (y >= 0) + { + if (d + y > 0) + { + ogHLine(xCenter-x, xCenter+x, yCenter-y, colour); + if (y != 0) ogHLine(xCenter-x, xCenter+x, yCenter+y, colour); + + --y; + d -= 4*y+1; + } // if + + + if (x > d) + { + ++x; + d += 4*x+1; + } // if + } // while +} // void ogSurface::ogFillCircle() + +void ogSurface::ogFillGouraudPolygon(uint32_t numPoints, ogPoint2d* polyPoints, ogRGBA8 * colours) +{ + + ogEdgeTable * edges; + int32 currentY = ~0; + + if (numPoints < 3) return; + + edges = new ogEdgeTable(); + + if (edges == NULL) return; // sanity check + + edges->BuildGET_G(numPoints, polyPoints, colours); + + if (edges->globalEdges != NULL) + currentY = edges->globalEdges->startY; + + while ((edges->globalEdges != NULL) || (edges->activeEdges != NULL)) + { + edges->MoveXSortedToAET(currentY); + edges->ScanOutAET_G(*this, currentY); + edges->AdvanceAET(); + edges->XSortAET(); + ++currentY; + if (currentY > (int32)maxY) break; // if we've gone past the bottom, stop + } // while + + delete edges; +} // void ogSurface::ogFillGouraudPolygon() + +void ogSurface::ogFillPolygon(uint32_t numPoints, ogPoint2d* polyPoints, uInt32 colour) +{ + ogEdgeTable * edges; + int32 currentY = ~0; + + if (numPoints < 3) return; + + if (!ogIsBlending()) ogPolygon(numPoints, polyPoints, colour); + + edges = new ogEdgeTable(); + + if (edges == NULL) return; // sanity check + + edges->BuildGET(numPoints, polyPoints); + + if (edges->globalEdges != NULL) + currentY = edges->globalEdges->startY; + + while ((edges->globalEdges != NULL) || (edges->activeEdges != NULL)) + { + edges->MoveXSortedToAET(currentY); + edges->ScanOutAET(*this, currentY, colour); + edges->AdvanceAET(); + edges->XSortAET(); + ++currentY; + if (currentY > (int32)maxY) break; // if we've gone past the bottom, stop + } // while + delete edges; +} // void ogSurface::ogFillPolygon() + + +void ogSurface::ogFillRect(int32 x1, int32 y1, int32 x2, int32 y2, uint32_t colour) +{ + int32 yy, tmp; + + if (x2 < x1) + { + tmp= x2; + x2 = x1; + x1 = tmp; + } // if + + if (y2 < y1) + { + tmp= y2; + y2 = y1; + y1 = tmp; + } // if + + if ((y2 < 0) || (y1 > (int32)maxY)) return; + if (y1 < 0) y1 = 0; + if (y2 > (int32)maxY) y2 = maxY; + for (yy = y1; yy <= y2; yy++) + ogHLine(x1, x2, yy, colour); +} // ogSurface::ogFillRect + +void ogSurface::ogFillTriangle(int32 x1, int32 y1, int32 x2, int32 y2, + int32 x3, int32 y3, uint32_t colour) +{ + ogPoint2d points[3]; + points[0].x = x1; + points[0].y = y1; + points[1].x = x2; + points[1].y = y2; + points[2].x = x3; + points[2].y = y3; + + ogFillPolygon(3, points, colour); + +} // void ogSurface::ogFillTriangle() +uint32_t ogSurface::ogGetAlpha(void) +{ + return (attributes != NULL ? attributes->defaultAlpha : 255L); +} // uint32_t ogSurface::ogGetAlpha() + +uint32_t ogSurface::ogGetColorCount() +{ + if (!ogAvail() || ogGetBytesPerPix() != 1) return 0; + + uint32_t colourCount = 0; + uint32_t colourCounter[256] = {}; + for (uint32_t y = 0; y <= ogGetMaxY(); y++) + { + for (uint32_t x = 0; x <= ogGetMaxX(); x++) + { + colourCounter[ogGetPixel(x, y)]++; + } // for x + } // for y + + for (size_t index = 0; index < std::extent::value; index++) + { + if (colourCounter[index] != 0) colourCount++; + } // for index + + return colourCount; +} // void ogSurface::ogCountColors() + +uint32_t ogSurface::ogGetPixel(int32 x, int32 y) +{ + if (!ogAvail()) return ogGetTransparentColor(); + + if (((uint32_t)x > maxX) || ((uInt32)y > maxY)) return ogGetTransparentColor(); + + return RawGetPixel(x, y); +} // uint32_t ogSurface::ogGetPixel() + +void ogSurface::ogGetPalette(ogRGBA8 _pal[256]) +{ + if (pal == NULL) return; + + for (size_t index = 0; index <256; index++) + { + _pal[index].red = pal[index].red; + _pal[index].green = pal[index].green; + _pal[index].blue = pal[index].blue; + _pal[index].alpha = pal[index].alpha; + } // for index +} // void ogSurface::ogGetPalette() + +void ogSurface::ogGetPixFmt(ogPixelFmt& pixfmt) +{ + pixfmt.BPP = BPP; + pixfmt.redFieldPosition = redFieldPosition; + pixfmt.greenFieldPosition = greenFieldPosition; + pixfmt.blueFieldPosition = blueFieldPosition; + pixfmt.alphaFieldPosition = alphaFieldPosition; + pixfmt.redMaskSize = 8-redShifter; + pixfmt.greenMaskSize = 8-greenShifter; + pixfmt.blueMaskSize = 8-blueShifter; + pixfmt.alphaMaskSize = 8-alphaShifter; +} // void ogSurface::ogGetPixFmt() + +void* ogSurface::ogGetPtr(uint32_t x, uInt32 y) +{ + // return (Avail() ? ( (uInt8*)buffer+(lineOfs[y]+x*((BPP+7) >> 3)) ) : NULL ); + return reinterpret_cast(buffer+(lineOfs[y]+x*bytesPerPix)); +} // void* ogSurface::ogGetPtr + +uint32_t ogSurface::ogGetTransparentColor(void) +{ + return (attributes != NULL ? attributes->transparentColor : 0); +} // ogSurface::ogGetTransparentColor + +void ogSurface::ogHFlip(void) +{ + void * tmpBuf1; + void * tmpBuf2; + uint32_t xWidth, count; + + if (!ogAvail()) return; + + xWidth = (maxX+1)*bytesPerPix; + +#ifdef __UBIXOS_KERNEL__ + tmpBuf1 = kmalloc(xWidth); + tmpBuf2 = kmalloc(xWidth); +#else + tmpBuf1 = malloc(xWidth); + tmpBuf2 = malloc(xWidth); +#endif + + if ((tmpBuf1 != NULL) && (tmpBuf2 != NULL)) + { + for (count = 0; count <= (maxY/2); count++) + { + ogCopyLineFrom(0, count, tmpBuf1, xWidth); + ogCopyLineFrom(0, maxY-count,tmpBuf2, xWidth); + ogCopyLineTo(0, maxY-count,tmpBuf1, xWidth); + ogCopyLineTo(0, count, tmpBuf2, xWidth); + } // for count + } +#ifdef __UBIXOS_KERNEL__ + kfree(tmpBuf2); + kfree(tmpBuf1); +#else + free(tmpBuf2); + free(tmpBuf1); +#endif + +} // void ogSurface::ogHFlip() + +void ogSurface::ogHLine(int32 x1, int32 x2, int32 y, uint32_t colour) +{ + int32 tmp; + uInt8 r, g, b, a; + + if (!ogAvail()) return; + if ((uint32_t)y > maxY) return; + + if (x1 > x2) + { + tmp= x1; + x1 = x2; + x2 = tmp; + } // if + + if (x1 < 0) x1 = 0; + if (x2 > (int32)maxX) x2 = maxX; + if (x2 < x1) return; + + if (ogIsBlending()) { + ogUnpack(colour, r, g, b, a); + if (a == 0) return; + if (a == 255) { + for (tmp = x1; tmp <= x2; tmp++) + RawSetPixel(tmp, y, r, g, b, a); + return; + } // if a == 255 + } // if blending + for (int32 xx = x1; xx <= x2; xx++) + RawSetPixel(xx, y, colour); + +} // void ogSurface::ogHLine() + +bool ogSurface::ogIsAntiAliasing(void) +{ + return (attributes != NULL ? attributes->antiAlias : false); +} // bool ogSurface::ogIsAntiAliasing() + +bool ogSurface::ogIsBlending(void) +{ + return (attributes != NULL ? attributes->blending : false); +} // bool ogSurface::ogIsBlending() + +void ogSurface::ogLine(int32 x1, int32 y1, int32 x2, int32 y2, uint32_t colour) +{ + if (ClipLine(x1,y1,x2,y2)) + { + if (ogIsAntiAliasing()) + AARawLine(x1, y1, x2, y2, colour); + else + RawLine(x1, y1, x2, y2, colour); + } // if clipLine + return; +} // void ogSurface::ogLine() + +bool ogSurface::ogLoadPalette(const char *palfile) +{ + ogRGBA8 oldPalette[256]; +#ifdef __UBIXOS_KERNEL__ + fileDescriptor *f; + This is possibly incompatible with the kernel. Will need a rewrite. +#endif + bool result; + + if (pal == NULL) + { + pal = new ogRGBA8[256]; + if (pal == NULL) + { + ogSetLastError(ogMemAllocFail); + return false; + } // if + ogSetPalette(DEFAULT_PALETTE); + // memcpy(pal, DEFAULT_PALETTE, sizeof(ogRGBA8)*256); + } // if + + ogGetPalette(oldPalette); + // memcpy(&oldPalette, pal, sizeof(ogRGBA8)*256); + + std::ifstream file; + file.open(palfile, std::ios::in | std::ios::binary); + + if (!file) + { + ogSetLastError(ogFileNotFound); + return false; + } // if !file + + size_t index = 0; + while (index < sizeof(pal) / sizeof(pal[0])) + { + if (!(file >> pal[index].red)) break; + if (!(file >> pal[index].green)) break; + if (!(file >> pal[index].blue)) break; + if (!(file >> pal[index].alpha)) break; + index++; + } + //lresult = fread(pal, sizeof(ogRGBA8), 256, f); + result = (index == 256); + + if (!result) + { + ogSetLastError(ogFileReadError); + ogSetPalette(oldPalette); + // memcpy(pal, &oldPalette, sizeof(ogRGBA8)*256); + } // if + + file.close(); + return result; +} // bool ogSurface::ogLoadPalette() + +void ogSurface::ogOptimize() +{ + if (!ogAvail() || ogGetBytesPerPix() != 1) return; + + int colourCounter[256] = {}; // count of how much that colour is used + size_t swapIndices[256]; // swap indices + size_t reverseIndices[256]; // reverse indices + ogRGBA8 pal[256]; // We also swap the palette entries + + // First acquire a count of all the colours used + for (uint32_t y = 0; y <= ogGetMaxY(); y++) + { + for (uint32_t x = 0; x <= ogGetMaxX(); x++) + { + colourCounter[ogGetPixel(x, y)]++; + } // for x + } // for y + + colourCounter[ogGetTransparentColor()] = INT_MAX; // set 0 so high it's always first + //SortDescending(colourCounter, swapIndices, 256); + + // Sort them in descending order + for (size_t i = 0; i < 256; i++) + swapIndices[i] = i; + + for (size_t k = 1; k < 256; k++) + { + for (size_t i = 0; i <256 - k; i++) + { + if (colourCounter[swapIndices[i]] < colourCounter[swapIndices[i+1]]) + { + size_t temp = swapIndices[i]; + swapIndices[i] = swapIndices[i+1]; + swapIndices[i+1] = temp; + } // if + } // for i + } // for k + + ogGetPalette(pal); + for (size_t i = 0; i < 256; i++) + { + reverseIndices[swapIndices[i]] = i; + //cout << "colourCounter[" << i << "] = " << swapIndices[i] << endl; + // Also swap the palette entries + ogSetPalette(i, pal[swapIndices[i]].red, pal[swapIndices[i]].green, pal[swapIndices[i]].blue); + } // for i + + for (uint32_t y = 0; y <= ogGetMaxY(); y++) + { + for (uint32_t x = 0; x <= ogGetMaxX(); x++) + { + ogSetPixel(x, y, reverseIndices[ogGetPixel(x, y)]); + } // for x + } // for y +} // void ogSurface::ogOptimize() + +uint32_t ogSurface::ogPack(uInt8 red, uInt8 green, uInt8 blue) +{ + uint32_t colour = 0; + + switch (bytesPerPix) { + case 4: + colour = ( (red << redFieldPosition) | + (green << greenFieldPosition) | + (blue << blueFieldPosition) | + (ogGetAlpha() << alphaFieldPosition) ); + break; + case 3: + colour = ( (red << redFieldPosition) | + (green << greenFieldPosition) | + (blue << blueFieldPosition) ); + break; + case 2: + colour = ((red >> redShifter) << redFieldPosition) | + ((green >> greenShifter) << greenFieldPosition) | + ((blue >> blueShifter) << blueFieldPosition) | + ((ogGetAlpha() >> alphaShifter) << alphaFieldPosition); + break; + case 1: + uint32_t dist = 255+255+255; + for (uint32_t idx = 0; idx <= 255; idx++) + { + uint32_t rd = abs(red-pal[idx].red); + uint32_t gd = abs(green-pal[idx].green); + uint32_t bd = abs(blue-pal[idx].blue); + uint32_t newdist = rd + gd + bd; + + if (newdist < dist) + { + dist = newdist; + colour = idx; + } // if + } // for + break; + } // switch + + return colour; + +} // uint32_t ogSurface::ogPack() + +uint32_t ogSurface::ogPack(uInt8 red, uInt8 green, uInt8 blue, uInt8 alpha) +{ + uint32_t colour = 0; + + switch (bytesPerPix) { + case 4: + colour = ( (red << redFieldPosition) | + (green << greenFieldPosition) | + (blue << blueFieldPosition) | + (alpha << alphaFieldPosition) ); + break; + case 3: + colour = ( (red << redFieldPosition) | + (green << greenFieldPosition) | + (blue << blueFieldPosition) ); + break; + case 2: + colour = ((red >> redShifter) << redFieldPosition) | + ((green >> greenShifter) << greenFieldPosition) | + ((blue >> blueShifter) << blueFieldPosition) | + ((alpha >> alphaShifter) << alphaFieldPosition); + break; + case 1: + uint32_t dist = 255+255+255; + for (uint32_t idx = 0; idx <= 255; idx++) + { + uint32_t rd = abs(red-pal[idx].red); + uint32_t gd = abs(green-pal[idx].green); + uint32_t bd = abs(blue-pal[idx].blue); + uint32_t newdist = rd + gd + bd; + + if (newdist < dist) + { + dist = newdist; + colour = idx; + } // if + } // for + break; + } // switch + + return colour; +} // uint32_t ogSurface::ogPack() + +void ogSurface::ogPolygon(uint32_t numPoints, ogPoint2d* polyPoints, uInt32 colour) +{ + if (polyPoints == NULL) return; + + if (numPoints == 1) + { + ogSetPixel(polyPoints[0].x, polyPoints[0].y, colour); + } + else + { + for (size_t count = 0; count < numPoints; count++) + ogLine(polyPoints[count].x, polyPoints[count].y, + polyPoints[(count+1) % numPoints].x, + polyPoints[(count+1) % numPoints].y, + colour); + } +} // void ogSurface::ogPolygon() + +void ogSurface::ogRect(int32 x1, int32 y1, int32 x2, int32 y2, uint32_t colour) +{ + if ((x1 == x2) || (y1 == y2)) + { + + if ((x1 == x2) && (y1 == y2)) + ogSetPixel(x1, y1, colour); + else + ogLine(x1, y1, x2, y2, colour); + + } + else + { + + if (y1 > y2) + { + int32 tmp= y1; + y1 = y2; + y2 = tmp; + } // if + + ogHLine(x1, x2, y1, colour); // Horizline has built in clipping + ogVLine(x1, y1+1, y2-1, colour); // vertline has built in clipping too + ogVLine(x2, y1+1, y2-1, colour); + ogHLine(x1, x2, y2, colour); + + } // else + +} // void ogSurface::ogRect() + +void ogSurface::ogScale(ogSurface& src) { + ogScaleBuf(0, 0, maxX, maxY, src, 0, 0, src.maxX, src.maxY); + return; +} // ogSurface::ogScale + +void ogSurface::ogScaleBuf(int32 dX1, int32 dY1, int32 dX2, int32 dY2, + ogSurface& src, + int32 sX1, int32 sY1, int32 sX2, int32 sY2) +{ + + uint32_t sWidth, dWidth; + uint32_t sHeight, dHeight; + int32 sx, sy, xx, yy; + uint32_t xInc, yInc; + uint32_t origdX1, origdY1; + ogPixelFmt pixFmt; + ogSurface * tmpBuf; + ogSurface * sBuf; + ogSurface * dBuf; + bool doCopyBuf; + + origdX1 = origdY1 = 0; // to keep the compiler from generating a warning + + if (!ogAvail()) return; + if (!src.ogAvail()) return; + + if (sX1 > sX2) + { + xx = sX1; + sX1= sX2; + sX2= xx; + } + + if (sY1 > sY2) + { + yy = sY1; + sY1= sY2; + sY2= yy; + } + + // if any part of the source falls outside the buffer then don't do anything + + if (((uint32_t)sX1 > src.maxX) || ((uInt32)sX2 > src.maxX) || + ((uint32_t)sY1 > src.maxY) || ((uInt32)sY2 > src.maxY)) return; + + if (dX1 > dX2) + { + xx = dX1; + dX1= dX1; + dX2= xx; + } + + if (dY1 > dY2) + { + yy = dY1; + dY1= dY2; + dY2= yy; + } + + dWidth = (dX2-dX1)+1; + if (dWidth <= 0) return; + + dHeight = (dY2-dY1)+1; + if (dHeight <= 0) return; + + sWidth = (sX2-sX1)+1; + sHeight = (sY2-sY1)+1; + + // convert into 16:16 fixed point ratio + xInc = (sWidth << 16) / dWidth; + yInc = (sHeight << 16) / dHeight; + + if (dX2 > (int32)maxX) + { + xx = (xInc*(dX1-maxX)) >> 16; + sX1 -= xx; + sWidth -= xx; + dWidth -= (dX1-maxX); + dX1 = maxX; + } + + if (dY2 > (int32)maxY) + { + yy = (yInc*(dY2-maxY)) >> 16; + sY2 -= yy; + sHeight -= yy; + dHeight -= (dY2-maxY); + dY2 = maxY; + } + + if (dX1 < 0) + { + xx = (xInc*(-dX1)) >> 16; + sX1 += xx; + sWidth -= xx; + dWidth += dX1; + dX1 = 0; + } + + if (dY1 < 0) + { + yy = (yInc*(-dY1)) >> 16; + sY1 += yy; + sHeight -= yy; + dHeight += dY1; + dY1 = 0; + } + + if ((dWidth <= 0) || (dHeight <= 0)) return; + if ((sWidth <= 0) || (sHeight <= 0)) return; + + // Do a quick check to see if the scale is 1:1 .. in that case just copy + // the image + + if ((dWidth == sWidth) && (dHeight == sHeight)) + { + ogCopyBuf(dX1, dY1, src, sX1, sY1, sX2, sY2); + return; + } + + tmpBuf = NULL; + + /* + * Alright.. this is how we're going to optimize the case of different + * pixel formats. We are going to use copyBuf() to automagically do + * the conversion for us using tmpBuf. Here's how it works: + * If the source buffer is smaller than the dest buffer (ie, we're making + * something bigger) we will convert the source buffer first into the dest + * buffer's pixel format. Then we do the scaling. + * If the source buffer is larger than the dest buffer (ie, we're making + * something smaller) we will scale first and then use copyBuf to do + * the conversion. + * This method puts the onus of conversion on the copyBuf() function which, + * while not excessively fast, does the job. + * The case in which the source and dest are the same size is handled above. + * + */ + if (pixFmtID != src.pixFmtID) + { + + tmpBuf = new ogSurface(); + if (tmpBuf == NULL) return; + if (sWidth*sHeight*src.bytesPerPix <= dWidth*dHeight*bytesPerPix) + { + // if the number of pixels in the source buffer is less than the + // number of pixels in the dest buffer then... + ogGetPixFmt(pixFmt); + if (!tmpBuf->ogCreate(sWidth, sHeight, pixFmt)) return; + tmpBuf->ogCopyPalette(src); + tmpBuf->ogCopyBuf(0, 0, src, sX1, sY1, sX2, sY2); + sX2 -= sX1; + sY2 -= sY1; + sX1 = 0; + sY1 = 0; + sBuf = tmpBuf; + dBuf = this; + doCopyBuf = false; // do we do a copyBuf later? + } + else + { + src.ogGetPixFmt(pixFmt); + if (!tmpBuf->ogCreate(dWidth,dHeight,pixFmt)) return; + tmpBuf->ogCopyPalette(*this); + origdX1 = dX1; + origdY1 = dY1; + dX1 = 0; + dY1 = 0; + dX2 = tmpBuf->maxX; + dY2 = tmpBuf->maxY; + sBuf = &src; + dBuf = tmpBuf; + doCopyBuf = true; + } // else + } + else + { + // pixel formats are identical + sBuf = &src; + dBuf = this; + doCopyBuf = false; + } // else + + sy = sY1 << 16; + + for (yy = dY1; yy <= dY2; yy++) + { + sx = 0; + for (xx = dX1; xx <= dX2; xx++) + { + dBuf->RawSetPixel(xx, yy, + sBuf->RawGetPixel(sX1+(sx >> 16),(sy>>16))); + sx += xInc; + } // for xx + sy += yInc; + } // for yy + + if ((doCopyBuf) && (tmpBuf != NULL)) + ogCopyBuf(origdX1, origdY1, *tmpBuf, 0, 0, tmpBuf->maxX, tmpBuf->maxY); + + delete tmpBuf; +} // void ogSurface::ogScaleBuf() + +uint32_t ogSurface::ogSetAlpha(uInt32 newAlpha) +{ + if (attributes != NULL) + { + uint32_t tmp = attributes->defaultAlpha; + attributes->defaultAlpha = newAlpha; + return tmp; + } + else + { + return newAlpha; + } +} // ogSurface::ogSetAlpha + +bool ogSurface::ogSetAntiAliasing(bool antiAliasing) +{ + if (attributes != NULL) + { + bool previousAA = attributes->antiAlias; + attributes->antiAlias = antiAliasing; + return previousAA; + } + else + { + return antiAliasing; // fail quietly + } +} // bool ogSurface::ogSetAntiAliasing() + +bool ogSurface::ogSetBlending(bool _blending) +{ + bool tmp; + + if (attributes != NULL) { + tmp = attributes->blending; + attributes->blending = _blending; + return tmp; + } else return _blending; + +} // bool ogSurface::ogSetBlending() + +ogErrorCode ogSurface::ogSetLastError(ogErrorCode latestError) +{ + ogErrorCode tmp = lastError; + lastError = latestError; + return tmp; +} // ogErrorCode ogSurface::ogSetLastError() + +void ogSurface::ogSetPalette(const ogRGBA8 newPal[256]) +{ + if (pal == NULL) return; + for (size_t index = 0; index < 256; index++) + { + pal[index].red = newPal[index].red; + pal[index].green = newPal[index].green; + pal[index].blue = newPal[index].blue; + pal[index].alpha = newPal[index].alpha; + } // for index +} // void ogSurface::ogSetPalette() + +void ogSurface::ogSetPalette(uInt8 colour, uInt8 red, uInt8 green, uInt8 blue, uInt8 alpha) +{ + if (pal == NULL) return; + pal[colour].red = red; + pal[colour].green = green; + pal[colour].blue = blue; + pal[colour].alpha = alpha; +} // void ogSurface::ogSetPalette() + +void ogSurface::ogSetPalette(uInt8 colour, uInt8 red, uInt8 green, uInt8 blue) +{ + if (pal == NULL) return; + pal[colour].red = red; + pal[colour].green = green; + pal[colour].blue = blue; + pal[colour].alpha = ogGetAlpha(); +} // void ogSurface::ogSetPalette() + +void ogSurface::ogSetPixel(int32 x, int32 y, uint32_t colour) +{ + if (!ogAvail()) return; + + if (((uint32_t)x > maxX) || ((uInt32)y > maxY)) return; + + RawSetPixel(x, y, colour); +} // void ogSurface::ogSetPixel() + +void ogSurface::ogSetPixel(int32 x, int32 y, uInt8 r, uInt8 g, uInt8 b, uInt8 a) { + if (!ogAvail()) return; + + if (((uint32_t)x > maxX) || ((uInt32)y > maxY)) return; + + RawSetPixel(x, y, r, g, b, a); +} // void ogSurface::ogSetPixel() + +uint32_t ogSurface::ogSetTransparentColor(uInt32 colour) +{ + uint32_t preColour = 0; + + if (attributes != NULL) + { + preColour = attributes->transparentColor & ogGetAlphaMasker(); + attributes->transparentColor = colour & ogGetAlphaMasker(); + } // if + + return preColour; +} // uint32_t ogSurface::ogSetTransparentColor() + +//static double f(double g) { return g*g*g-g; } + +void ogSurface::ogSpline(uint32_t numPoints, ogPoint2d* points, uInt32 segments, + uint32_t colour) +{ + int32 i, oldY, oldX, x, y, j; + double part, t, xx, yy, tmp; + double * zc; + double * dx; + double * dy; + double * u; + double * wndX1; + double * wndY1; + double * px; + double * py; + + auto f = ([] (double g) -> double { return g*g*g*-g; }); + bool runOnce; + + if ((numPoints < 2) || (points == NULL)) return; + + zc = new double[numPoints]; + dx = new double[numPoints]; + dy = new double[numPoints]; + u = new double[numPoints]; + wndX1 = new double[numPoints]; + wndY1 = new double[numPoints]; + px = new double[numPoints]; + py = new double[numPoints]; + + do { + if (zc == NULL) break; + if (dx == NULL) break; + if (dy == NULL) break; + if (wndX1 == NULL) break; + if (wndY1 == NULL) break; + if (px == NULL) break; + if (py == NULL) break; + + for (i = 0; (uint32_t)i < numPoints; i++) + { + zc[i] = dx[i] = dy[i] = u[i] = wndX1[i] = wndY1[i] = px[i] = py[i] = 0.0f; + } + + runOnce = false; + oldX = oldY = 0; + + x = points[0].x; + y = points[0].y; + + for (i = 1; (uint32_t)i < numPoints; i++) + { + xx = points[i-1].x - points[i].x; + yy = points[i-1].y - points[i].y; + t = sqrt(xx*xx + yy*yy); + zc[i] = zc[i-1]+t; + } // for + + u[0] = zc[1] - zc[0] +1; + for (i = 1; (uint32_t)i < numPoints-1; i++) + { + u[i] = zc[i+1]-zc[i]+1; + tmp = 2*(zc[i+1]-zc[i-1]); + dx[i] = tmp; + dy[i] = tmp; + wndY1[i] = 6.0f*((points[i+1].y-points[i].y)/u[i]- + (points[i].y-points[i-1].y)/u[i-1]); + wndX1[i] = 6.0f*((points[i+1].x-points[i].x)/u[i]- + (points[i].x-points[i-1].x)/u[i-1]); + } // for + + for (i = 1; (uint32_t)i < numPoints-2; i++) + { + wndY1[i+1] = wndY1[i+1]-wndY1[i]*u[i]/dy[i]; + dy[i+1] = dy[i+1]-u[i]*u[i]/dy[i]; + wndX1[i+1] = wndX1[i+1]-wndX1[i]*u[i]/dx[i]; + dx[i+1] = dx[i+1]-u[i]*u[i]/dx[i]; + } // for + + for (i = numPoints-2; i > 0; i--) + { + py[i] = (wndY1[i]-u[i]*py[i+1])/dy[i]; + px[i] = (wndX1[i]-u[i]*px[i+1])/dx[i]; + } // for + + for (i = 0; (uint32_t)i < numPoints-1; i++) + { + for (j = 0; (uint32_t)j <= segments; j++) + { + part = zc[i]-(((zc[i]-zc[i+1])/segments)*j); + t = (part-zc[i])/u[i]; + part = t * points[i+1].y + + (1.0-t)*points[i].y + + u[i] * u[i] * ( f(t) * py[i+1] + f(1.0-t) * py[i]) /6.0; + // y = Round(part); + y = static_cast(part+0.5f); + part = zc[i]-(((zc[i]-zc[i+1])/segments)*j); + t = (part-zc[i])/u[i]; + part = t*points[i+1].x+(1.0-t)*points[i].x+u[i]*u[i]*(f(t)*px[i+1]+ + f(1.0-t)*px[i])/6.0; + + // x = Round(part); + x = static_cast(part+0.5f); + if (runOnce) ogLine(oldX, oldY, x, y, colour); else runOnce = true; + oldX = x; + oldY = y; + } // for j + } // for i + } while (false); + + delete [] py; + delete [] px; + delete [] wndY1; + delete [] wndX1; + delete [] u; + delete [] dy; + delete [] dx; + delete [] zc; + +} // void ogSurface::ogSpline() + +void ogSurface::ogTriangle(int32 x1, int32 y1, int32 x2, int32 y2, int32 x3, int32 y3, uint32_t colour) +{ + ogLine(x1, y1, x2, y2,colour); + ogLine(x2, y2, x3, y3,colour); + ogLine(x3, y3, x1, y1,colour); +} // void ogSurface::ogTriangle() + +void ogSurface::ogUnpack(uint32_t colour, uInt8& red, uInt8& green, uInt8& blue) +{ + switch (bytesPerPix) + { + case 4: + case 3: + red = colour >> redFieldPosition; + green = colour >> greenFieldPosition; + blue = colour >> blueFieldPosition; + break; + case 2: + red = ((colour >> redFieldPosition) << redShifter); + green = ((colour >> greenFieldPosition) << greenShifter); + blue = ((colour >> blueFieldPosition) << blueShifter); + if (red != 0) red += ogPixelFmt::OG_MASKS[redShifter]; + if (green != 0) green += ogPixelFmt::OG_MASKS[greenShifter]; + if (blue != 0) blue += ogPixelFmt::OG_MASKS[blueShifter]; + break; + case 1: + + if (pal == NULL) + { + red = green = blue = 0; + return; + } // if pal == null + + if (colour > 255) colour &= 255; + red = pal[colour].red; + green = pal[colour].green; + blue = pal[colour].blue; + break; + default: + red = 0; + green = 0; + blue = 0; + } // switch + +} // void ogSurface::ogUnpack() + +void ogSurface::ogUnpack(uint32_t colour, uInt8& red, uInt8& green, uInt8& blue, uInt8& alpha) +{ + + switch (bytesPerPix) { + case 4: + red = colour >> redFieldPosition; + green = colour >> greenFieldPosition; + blue = colour >> blueFieldPosition; + alpha = colour >> alphaFieldPosition; + break; + case 3: + red = colour >> redFieldPosition; + green = colour >> greenFieldPosition; + blue = colour >> blueFieldPosition; + alpha = ogGetAlpha(); + break; + case 2: + red = ((colour >> redFieldPosition) << redShifter); + green = ((colour >> greenFieldPosition) << greenShifter); + blue = ((colour >> blueFieldPosition) << blueShifter); + if (red != 0) red += ogPixelFmt::OG_MASKS[redShifter]; + if (green != 0) green += ogPixelFmt::OG_MASKS[greenShifter]; + if (blue != 0) blue += ogPixelFmt::OG_MASKS[blueShifter]; + + if (alphaShifter != 8) { + alpha = (colour >> alphaFieldPosition) << alphaShifter; + if (alpha != 0) alpha += ogPixelFmt::OG_MASKS[alphaShifter]; + } else alpha = ogGetAlpha(); + + break; + case 1: + + if (pal == NULL) + { + red = green = blue = alpha = 0; + return; + } // if pal == null + + if (colour > 255) colour &= 255; + red = pal[colour].red; + green = pal[colour].green; + blue = pal[colour].blue; + alpha = pal[colour].alpha; + break; + default: + red = green = blue = alpha = 0; + } // switch + + return; +} // void ogSurface::ogUnpack() + +void ogSurface::ogVFlip() +{ + if (!ogAvail()) return; + + for (uint32_t yy = 0; yy <= maxY; yy++) + { + for (uint32_t xx = 0; xx < maxX/2; xx++) + { + uint32_t swapColour = RawGetPixel(xx, yy); + RawSetPixel(xx, yy, RawGetPixel(maxX-xx, yy)); + RawSetPixel(maxX-xx, yy, swapColour); + } // for xx + } // for yy +} // void ogSurface::ogVFlip() + +void ogSurface::ogVLine(int32 x, int32 y1, int32 y2, uint32_t colour) +{ + int32 tmp; + uInt8 r, g, b, a; + + if (!ogAvail()) return; + if ((uint32_t)x > maxX) return; + + if (y1 > y2) + { + tmp= y1; + y1 = y2; + y2 = tmp; + } // if + + if (y1 < 0) y1 = 0; + if (y2 > (int32)maxY) y2 = maxY; + if (y2 < y1) return; + + if (ogIsBlending()) { + + ogUnpack(colour, r, g, b, a); + + if (a == 0) return; + + if (a != 255) { + for (tmp = y1; tmp <= y2; tmp++) + RawSetPixel(x, tmp, r, g, b, a); + return; + } // if + + } // if blending + for (int32 yy = y1; yy <= y2; yy++) + { + RawSetPixel(x, yy, colour); + } +} // void ogSurface::ogVLine() + +ogSurface::~ogSurface(void) { + + if (dataState == ogOwner) + { + delete [] pal; + delete [] lineOfs; + delete attributes; +#ifdef __UBIXOS_KERNEL__ + kfree(buffer); +#else + free(buffer); +#endif + } // if datastate == ogOwner + + pal = NULL; + lineOfs= NULL; + buffer = NULL; + attributes = NULL; + bSize = 0; + lSize = 0; + dataState = ogNone; + return; +} // ogSurface::~ogSurface diff --git a/sys/include/sde/sde.h b/sys/include/sde/sde.h index a16a911..4454434 100644 --- a/sys/include/sde/sde.h +++ b/sys/include/sde/sde.h @@ -29,6 +29,7 @@ #define _SDE_SDE_H #include +#include #ifdef __cplusplus extern "C" { @@ -41,7 +42,8 @@ void sdeThread(); -void sysSDE(uint32_t cmd, void *ptr); +//void sysSDE(uint32_t cmd, void *ptr); +int sysSDE(struct thread *td, struct sys_sde_args *args); struct sdeWindows { struct sdeWindows *next; diff --git a/sys/include/sys/sysproto.h b/sys/include/sys/sysproto.h index 159f2ef..8c77888 100644 --- a/sys/include/sys/sysproto.h +++ b/sys/include/sys/sysproto.h @@ -77,6 +77,15 @@ char msg_r_[PADR_(const void *)]; }; +struct sys_sde_args { + char cmd_l_[PADL_(uint32_t)]; + uint32_t cmd; + char cmd_r_[PADR_(uint32_t)]; + char ptr_l_[PADL_(void *)]; + void *ptr; + char ptr_r_[PADR_(void *)]; +}; + //Func Defs int sys_invalid(struct thread *, void *); diff --git a/sys/kernel/syscall.c b/sys/kernel/syscall.c index 0564eba..6a97508 100644 --- a/sys/kernel/syscall.c +++ b/sys/kernel/syscall.c @@ -82,10 +82,11 @@ return; } +kprintf("ERROR: 0x%X",error); switch (error) { case 0: frame->tf_eax = td->td_retval[0]; - frame->tf_edx = td->td_retval[1]; + // frame->tf_edx = td->td_retval[1]; frame->tf_eflags &= ~PSL_C; break; default: diff --git a/sys/kernel/syscalls.c b/sys/kernel/syscalls.c index 3222144..1a04c4d 100644 --- a/sys/kernel/syscalls.c +++ b/sys/kernel/syscalls.c @@ -28,6 +28,7 @@ #include #include +#include /* System Calls List */ struct syscall_entry systemCalls[] = { @@ -70,9 +71,9 @@ { 0, "No Call", sys_invalid, SYSCALL_VALID }, // 1 - { 0, "No Call", sys_invalid, SYSCALL_VALID }, // 1 - { 0, "No Call", sys_invalid, SYSCALL_VALID }, // 1 - - { 0, "No Call", sys_invalid, SYSCALL_VALID }, // 1 - - { 0, "No Call", sys_invalid, SYSCALL_VALID }, // 1 - - { 0, "No Call", sys_invalid, SYSCALL_VALID }, // 1 - + { 0, "No Call", sys_invalid, SYSCALL_VALID }, // 39 - + { ARG_COUNT(sys_sde_args), "sysSDE", sysSDE, SYSCALL_VALID }, // 40 - + { 0, "No Call", sys_invalid, SYSCALL_VALID }, // 41 - { 0, "No Call", sys_invalid, SYSCALL_VALID }, // 1 - { 0, "No Call", sys_invalid, SYSCALL_VALID }, // 1 - { 0, "No Call", sys_invalid, SYSCALL_VALID }, // 1 - diff --git a/sys/sde/main.cc b/sys/sde/main.cc index 71e3584..d00dcb4 100644 --- a/sys/sde/main.cc +++ b/sys/sde/main.cc @@ -65,7 +65,9 @@ screen->ogCreate(800, 600, OG_PIXFMT_24BPP); - screen->ogClear(screen->ogPack(122, 140, 163)); + //screen->ogClear(screen->ogPack(122, 140, 163)); + //screen->ogClear(screen->ogPack(0x66, 0xE0, 0xFF)); + screen->ogClear(screen->ogPack(0x92, 0xA8, 0xD1)); systemVitals->screen = screen; systemVitals->font = font; @@ -86,6 +88,7 @@ for (tmp = windows; tmp; tmp = tmp->next) { switch (tmp->status) { case registerWindow: + kprintf("buf->buffer 0x%X, buf->bSize: 0x%X", buf->buffer, buf->bSize); buf = (ogSurface *) tmp->buf; buf->buffer = (void *) vmm_mapFromTask(tmp->pid, buf->buffer, buf->bSize); if (buf->buffer == 0x0) { @@ -93,6 +96,9 @@ while (1) asm("nop"); } + + + kprintf("buf->lineOfs 0x%X, buf->lSize: 0x%X", buf->lineOfs, buf->lSize); buf->lineOfs = (uInt32 *) vmm_mapFromTask(tmp->pid, buf->lineOfs, buf->lSize); if (buf->lineOfs == 0x0) { kprintf("Error: buf->lineOfs\n"); diff --git a/sys/sde/sde.cc b/sys/sde/sde.cc index 375b271..157bc80 100644 --- a/sys/sde/sde.cc +++ b/sys/sde/sde.cc @@ -40,10 +40,12 @@ struct sdeWindows *windows = 0x0; -extern "C" void sysSDE(uInt32 cmd, void *ptr) { +//extern "C" void sysSDE(uInt32 cmd, void *ptr) { +extern "C" int sysSDE(struct thread *td, struct sys_sde_args *args) { ogSurface *newBuf = 0x0; - ogSurface *oldBuf = (ogSurface *) ptr; + ogSurface *oldBuf = (ogSurface *) args->ptr; struct sdeWindows *tmp = 0x0; + kprintf("\nCMD: %i:0x%X\n", args->cmd, args->ptr); for (tmp = windows; tmp; tmp = tmp->next) { if (tmp->pid == (int) _current->id) @@ -54,12 +56,14 @@ while (tmp->status != windowReady) asm("hlt"); } - else if (tmp == 0x0 && cmd != registerWindow) { + else if (tmp == 0x0 && args->cmd != registerWindow) { kprintf("Invalid Window\n"); - return; + td->td_retval[0] = -1; + return(-1); } - switch (cmd) { + + switch (args->cmd) { case drawWindow: tmp->status = drawWindow; while (tmp->status != windowReady) { @@ -118,10 +122,12 @@ } break; default: - kprintf("Invalid SDE Command [0x%X]\n", ptr); + kprintf("Invalid SDE Command [0x%X]\n", args->ptr); break; } - return; + kprintf("Here"); + td->td_retval[0] = 0; + return(0); } /*** diff --git a/sys/vmm/paging.c b/sys/vmm/paging.c index 31410c9..0810f18 100644 --- a/sys/vmm/paging.c +++ b/sys/vmm/paging.c @@ -377,7 +377,7 @@ void *vmm_mapFromTask(pidType pid, void *ptr, uint32_t size) { kTask_t *child = 0x0; uint32_t i = 0x0, x = 0x0, y = 0x0, count = ((size + 4095) / 0x1000), c = 0x0; - uInt16 dI = 0x0, tI = 0x0; + uInt32 dI = 0x0, tI = 0x0; uint32_t baseAddr = 0x0, offset = 0x0; uint32_t *childPageDir = (uint32_t *) 0x5A00000; uint32_t *childPageTable = 0x0; @@ -389,14 +389,18 @@ dI = (baseAddr / (1024 * 4096)); tI = ((baseAddr - (dI * (1024 * 4096))) / 4096); + kprintf("cr3: 0x%X\n", child->tss.cr3); if (vmm_remapPage(child->tss.cr3, 0x5A00000, KERNEL_PAGE_DEFAULT, _current->id, 0) == 0x0) K_PANIC("vmm_remapPage: Failed"); for (i = 0; i < 0x1000; i++) { + if ((childPageDir[i] & PAGE_PRESENT) == PAGE_PRESENT) { if (vmm_remapPage(childPageDir[i], 0x5A01000 + (i * 0x1000), KERNEL_PAGE_DEFAULT, _current->id, 0) == 0x0) K_PANIC("Returned NULL"); + } } - for (x = (_current->oInfo.vmStart / (1024 * 4096)); x < 1024; x++) { + //for (x = (_current->oInfo.vmStart / (1024 * 4096)); x < 1024; x++) { + for (x = PD_INDEX(VMM_KERNEL_START); x < PD_INDEX(VMM_KERNELEND); x++) { kpanic("v_mFT"); pageTableSrc = (uint32_t *) (PT_BASE_ADDR + (4096 * x)); @@ -429,10 +433,16 @@ } +kprintf("dI: 0x%X", dI); +if ((childPageDir[dI] & PAGE_PRESENT) == PAGE_PRESENT) { childPageTable = (uint32_t *) (0x5A01000 + (0x1000 * dI)); +if ((childPageTable[tI + c] & PAGE_PRESENT) == PAGE_PRESENT) { if (vmm_remapPage(childPageTable[tI + c], ((x * (1024 * 4096)) + ((y + c) * 4096)), KERNEL_PAGE_DEFAULT, _current->id, 0) == 0x0) K_PANIC("remap == NULL"); +} +} + } @@ -451,9 +461,13 @@ //Map A Physical Page To The Virtual Page childPageTable = (uint32_t *) (0x5A01000 + (0x1000 * dI)); - +kprintf("eDI: 0x%X", dI); +if ((childPageDir[dI] & PAGE_PRESENT) == PAGE_PRESENT) { +if ((childPageTable[tI] & PAGE_PRESENT) == PAGE_PRESENT) { if (vmm_remapPage(childPageTable[tI], ((x * (1024 * 4096)) + (y * 4096)), KERNEL_PAGE_DEFAULT, _current->id, 0) == 0x0) K_PANIC("remap Failed"); +} +} //Return The Address Of The Mapped In Memory vmm_unmapPage(0x5A00000, 1);