From 6c5e7bb8cc6de329e9fa478e234a955bde8bf558 Mon Sep 17 00:00:00 2001 From: cxl Date: Fri, 9 Jan 2009 16:40:06 +0000 Subject: [PATCH] SDraw radial gradients git-svn-id: svn://ultimatepp.org/upp/trunk@736 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppdev/Queue/Patrik.cpp | 144 +++++++++++++++ uppdev/Queue/Queue.cpp | 1 + uppdev/Queue/Queue.upp | 1 + uppdev/Queue/init | 4 + uppdev/SDraw/Fill.cpp | 202 +++++++++++++++++++-- uppdev/SDraw/Gradient.cpp | 70 ++++---- uppdev/SDraw/RadialGradient.cpp | 216 ++++++++++++++++++++++ uppdev/SDraw/SDraw.cpp | 9 +- uppdev/SDraw/SDraw.h | 50 ++++-- uppdev/SDraw/SDraw.upp | 1 + uppdev/SDraw/agg_span_image_filter_upp.h | 130 +++++++------- uppdev/SDrawTest/main.cpp | 137 ++++++++++++-- uppdev/bsr/bsr.cpp | 220 +++++++++++++++++++++++ uppdev/bsr/bsr.upp | 9 + 14 files changed, 1055 insertions(+), 139 deletions(-) create mode 100644 uppdev/Queue/Patrik.cpp create mode 100644 uppdev/Queue/init create mode 100644 uppdev/SDraw/RadialGradient.cpp create mode 100644 uppdev/bsr/bsr.cpp create mode 100644 uppdev/bsr/bsr.upp diff --git a/uppdev/Queue/Patrik.cpp b/uppdev/Queue/Patrik.cpp new file mode 100644 index 000000000..5c17c028c --- /dev/null +++ b/uppdev/Queue/Patrik.cpp @@ -0,0 +1,144 @@ +// Solution to our pre-interview test. + +#include +#include + +// Macros I can't do without anymore. + +#define hope(x) while ( ! (x) ) { onIllegalOperation() ; } +#define require(x) typedef char require[ (x) ? 1 : -1 ] ; + +// Error handlers. + +#define onOutOfMemory() do{ fprintf( stderr, "Out of memory!\n" ) ; exit( EXIT_FAILURE ) ; } while( 0 ) +#define onIllegalOperation() do{ fprintf( stderr, "Illegal Operation!\n" ) ; exit( EXIT_FAILURE ) ; } while( 0 ) + +// Typedefs. + +typedef unsigned char byte ; +typedef unsigned int uint ; + +struct Q { + uint first ; + uint last ; +} ; + +// Constants. + +const uint BLOCK_SIZE = 8 ; +const uint BLOCK_MASK = BLOCK_SIZE - 1 ; +const uint BLOCK_LAST = BLOCK_SIZE - 1 ; +const uint TOTAL_SIZE = 2048 ; +const uint BLOCK_COUNT = TOTAL_SIZE / BLOCK_SIZE ; + +// The provided memory, and appropriate aliasing. +// +// Everything is split to 256 8byte blocks. +// +// Blocks 1-255 are used for both queues and data, block 0 for book-keeping of free blocks. +// data[ 0 ] maintains single linked list of free blocks, while +// data[ 1 ] keeps the index of the last block ever allocated. +// Both used and free blocks are linked via their last byte. +// +// Note that array requires alignment to uint on some architectures, +// which is simple to achieve with "aligned" attribute if necessary. +// The alternative would be to use aligned memory within it ourselves. + +byte data[ TOTAL_SIZE ] ; + +#define queues ((Q *)(data)) + +require( sizeof( Q ) == BLOCK_SIZE ) ; + +// Block management. + +static byte allocate_block( void ) +{ + // Use one of the freed blocks, if possible. + + byte block = data[ 0 ] ; + if ( block ) { + data[ 0 ] = data[ block * BLOCK_SIZE + BLOCK_LAST ] ; + return block ; + } + + // Otherwise grab new block from the array, if possible. + // + // We can use an arguable trick that it will overflow in case we run out of blocks. + // This may be considered either cool or entirely intorelable, depending on the point of view. + + require( BLOCK_COUNT == 256 ) ; + + block = ++data[ 1 ] ; + if ( block ) { + return block ; + } + + // Well, bad luck. + + onOutOfMemory() ; +} + +static void free_block( const byte block ) +{ + hope( block > 0 ) ; + hope( block < BLOCK_COUNT ) ; + + data[ block * BLOCK_SIZE + BLOCK_LAST ] = data[ 0 ] ; + data[ 0 ] = block ; +} + +// Queue methods themselves, each O(1). + +Q * createQ( void ) +{ + Q * const q = queues + allocate_block() ; + q->first = q->last = allocate_block() * BLOCK_SIZE ; + return q ; +} + +void destroyQ( Q * q ) +{ + hope( q ) ; + + data[ q->last | BLOCK_MASK ] = data[ 0 ] ; + data[ 0 ] = q->first / BLOCK_SIZE ; + + free_block( q - queues ) ; +} + +void enQ( Q * q, byte n ) +{ + hope( q ) ; + + if ( q->last & BLOCK_MASK == BLOCK_LAST ) { + const byte block = allocate_block() ; + data[ q->last ] = block ; + q->last = block * BLOCK_SIZE ; + } + data[ q->last++ ] = n ; +} + +byte deQ( Q * q ) +{ + hope( q ) ; + + if ( q->first == q->last ) { + onIllegalOperation() ; + } + if ( q->first & BLOCK_MASK == BLOCK_LAST ) { + const byte block = data[ q->first ] ; + free_block( q->first / BLOCK_SIZE ) ; + q->first = block * BLOCK_SIZE ; + } + return data[ q->first++ ] ; +} + +void TestPatrik() +{ + Q *q0 = createQ(); + for(int i = 0; i < 3000; i++) { + DDUMP(i); + enQ(q0, 0); + } +} diff --git a/uppdev/Queue/Queue.cpp b/uppdev/Queue/Queue.cpp index 46530e6b6..158d661e8 100644 --- a/uppdev/Queue/Queue.cpp +++ b/uppdev/Queue/Queue.cpp @@ -155,3 +155,4 @@ CONSOLE_APP_MAIN for(int i = 0; i < 128 * 15; i++) DUMP((int)a1.Get()); } + diff --git a/uppdev/Queue/Queue.upp b/uppdev/Queue/Queue.upp index e839a3f28..690c47bc4 100644 --- a/uppdev/Queue/Queue.upp +++ b/uppdev/Queue/Queue.upp @@ -2,6 +2,7 @@ uses Core; file + Patrik.cpp, Queue.cpp; mainconfig diff --git a/uppdev/Queue/init b/uppdev/Queue/init new file mode 100644 index 000000000..39f96f154 --- /dev/null +++ b/uppdev/Queue/init @@ -0,0 +1,4 @@ +#ifndef _Queue_icpp_init_stub +#define _Queue_icpp_init_stub +#include "Core/init" +#endif diff --git a/uppdev/SDraw/Fill.cpp b/uppdev/SDraw/Fill.cpp index 67d93a5ad..d5d43b3d1 100644 --- a/uppdev/SDraw/Fill.cpp +++ b/uppdev/SDraw/Fill.cpp @@ -37,29 +37,164 @@ SDraw& SDraw::Fill(const RGBA& c) return *this; } +struct UppImageAggSpan { + struct RGBAV { + dword r, g, b, a; + + void Set(dword v) { r = g = b = a = v; } + void Put(dword weight, const RGBA& src) { + r += weight * src.r; + g += weight * src.g; + b += weight * src.b; + a += weight * src.a; + } + }; + + agg::span_interpolator_linear<> interpolator; + int ax, ay, cx, cy, maxx, maxy; + byte style; + byte hstyle, vstyle; + bool fast; + bool fixed; + const RGBA *image; + int alpha; + + void SetAlpha(int a) { alpha = a + (a >> 7); } + + void SetImage(const Image& img) { + image = ~img; + cx = img.GetWidth(); + cy = img.GetHeight(); + maxx = cx - 1; + maxy = cy - 1; + ax = 6000000 / cx * cx; + ay = 6000000 / cy * cy; + } + + RGBA Pixel(int x, int y) { return image[cx * y + x]; } + + RGBA GetPixel(int x, int y) { + if(hstyle == FILL_HPAD) + x = minmax(x, 0, maxx); + else + if(hstyle == FILL_HREFLECT) + x = (x + ax) / cx & 1 ? (ax - x - 1) % cx : (x + ax) % cx; + else + if(hstyle == FILL_HREPEAT) + x = (x + ax) % cx; + if(vstyle == FILL_VPAD) + y = minmax(y, 0, maxy); + else + if(vstyle == FILL_VREFLECT) + y = (y + ay) / cy & 1 ? (ay - y - 1) % cy : (y + ay) % cy; + else + if(vstyle == FILL_VREPEAT) + y = (y + ay) % cy; + return fixed || (x >= 0 && x < cx && y >= 0 && y < cy) ? image[cx * y + x] : RGBAZero(); + } + + void prepare() {} + + void generate(agg::rgba8 *_span, int x, int y, unsigned len) { + interpolator.begin(x + 0.5, y + 0.5, len); + RGBA *span = (RGBA *)_span; + fixed = hstyle && vstyle; + while(len--) { + int x_hr; + int y_hr; + interpolator.coordinates(&x_hr, &y_hr); + x_hr -= 128; + y_hr -= 128; + int x_lr = x_hr >> 8; + int y_lr = y_hr >> 8; + if(hstyle == FILL_HREPEAT) + x_lr = (x_lr + ax) % cx; + if(vstyle == FILL_VREPEAT) + y_lr = (y_lr + ay) % cy; + if(fast) { + RGBA v; + if(x_lr > 0 && x_lr < maxx && y_lr > 0 && y_lr < maxy) + v = Pixel(x_lr, y_lr); + if(style == 0 && (x_lr < -1 || x_lr > cx || y_lr < -1 || y_lr > cy)) + v == RGBAZero(); + else + v = GetPixel(x_lr, y_lr); + if(alpha == 256) + *span = v; + else { + span->r = byte((alpha * v.r) >> 8); + span->g = byte((alpha * v.g) >> 8); + span->b = byte((alpha * v.b) >> 8); + span->a = byte((alpha * v.a) >> 8); + } + } + else { + RGBAV v; + v.Set(256 * 256 / 2); + x_hr &= 255; + y_hr &= 255; + if(x_lr > 0 && x_lr < maxx && y_lr > 0 && y_lr < maxy) { + v.Put((256 - x_hr) * (256 - y_hr), Pixel(x_lr, y_lr)); + v.Put(x_hr * (256 - y_hr), Pixel(x_lr + 1, y_lr)); + v.Put((256 - x_hr) * y_hr, Pixel(x_lr, y_lr + 1)); + v.Put(x_hr * y_hr, Pixel(x_lr + 1, y_lr + 1)); + } + else + if(style == 0 && (x_lr < -1 || x_lr > cx || y_lr < -1 || y_lr > cy)) + v.Set(0); + else { + v.Put((256 - x_hr) * (256 - y_hr), GetPixel(x_lr, y_lr)); + v.Put(x_hr * (256 - y_hr), GetPixel(x_lr + 1, y_lr)); + v.Put((256 - x_hr) * y_hr, GetPixel(x_lr, y_lr + 1)); + v.Put(x_hr * y_hr, GetPixel(x_lr + 1, y_lr + 1)); + } + v.r >>= 16; + v.g >>= 16; + v.b >>= 16; + v.a >>= 16; + if(alpha == 256) { + span->r = (byte)v.r; + span->g = (byte)v.g; + span->b = (byte)v.b; + span->a = (byte)v.a; + } + else { + span->r = byte((alpha * v.r) >> 8); + span->g = byte((alpha * v.g) >> 8); + span->b = byte((alpha * v.b) >> 8); + span->a = byte((alpha * v.a) >> 8); + } + } + ++span; + ++interpolator; + } + } +}; + +#if 1 SDraw& SDraw::Fill(const Image& image, const Matrix2D& transsrc, dword flags) { if(image.GetWidth() == 0 || image.GetHeight() == 0) return *this; - span_alloc sa; - Matrix2D m = transsrc * pathattr.mtx; - m.invert(); - interpolator_type interpolator(m); - Size isz = image.GetSize(); - agg::rendering_buffer buf((agg::int8u*)~image, isz.cx, isz.cy, isz.cx * sizeof(RGBA)); - pixfmt img_pixf(buf); if(inpath) path.close_polygon(); + span_alloc sa; + + Matrix2D m = transsrc * pathattr.mtx; + m.invert(); + UppImageAggSpan sg; + sg.interpolator.transformer(m); + sg.SetAlpha(int(pathattr.opacity * 255)); + sg.SetImage(image); + sg.style = flags & 15; + sg.hstyle = flags & 3; + sg.vstyle = flags & 12; + sg.fast = flags & FILL_FAST; + rasterizer.reset(); rasterizer.filling_rule(pathattr.evenodd ? agg::fill_even_odd : agg::fill_non_zero); rasterizer.add_path(curved_trans); - span_gen_type sg(img_pixf, agg::rgba8_pre(0, 0, 0, 0), interpolator); - sg.alpha(int(pathattr.opacity * 255)); - sg.tile(flags & FILL_REPEAT); - if(flags & FILL_HCOPY) - sg.hcopy(); - if(flags & FILL_VCOPY) - sg.vcopy(); + if(clip.GetCount()) { agg::rendering_buffer mask_rbuf; mask_rbuf.attach(~clip.Top(), size.cx, size.cy, size.cx); @@ -73,6 +208,45 @@ SDraw& SDraw::Fill(const Image& image, const Matrix2D& transsrc, dword flags) inpath = false; return *this; } +#else +SDraw& SDraw::Fill(const Image& image, const Matrix2D& transsrc, dword flags) +{ + if(image.GetWidth() == 0 || image.GetHeight() == 0) + return *this; + span_alloc sa; + Matrix2D m = transsrc * pathattr.mtx; + m.invert(); + agg::span_interpolator_linear<> interpolator(m); + Size isz = image.GetSize(); + agg::rendering_buffer buf((agg::int8u*)~image, isz.cx, isz.cy, isz.cx * sizeof(RGBA)); + pixfmt img_pixf(buf); + if(inpath) + path.close_polygon(); + rasterizer.reset(); + rasterizer.filling_rule(pathattr.evenodd ? agg::fill_even_odd : agg::fill_non_zero); + rasterizer.add_path(curved_trans); + span_gen_type sg(img_pixf, agg::rgba8_pre(0, 0, 0, 0), interpolator); + sg.alpha(int(pathattr.opacity * 255)); + sg.hcopy = flags & FILL_HPAD; + sg.vcopy = flags & FILL_VPAD; + sg.hrepeat = flags & FILL_HREPEAT; + sg.vrepeat = flags & FILL_VREPEAT; + sg.hreflect = flags & FILL_HREFLECT; + sg.vreflect = flags & FILL_VREFLECT; + if(clip.GetCount()) { + agg::rendering_buffer mask_rbuf; + mask_rbuf.attach(~clip.Top(), size.cx, size.cy, size.cx); + agg::alpha_mask_gray8 mask(mask_rbuf); + agg::scanline_u8_am sl(mask); + agg::render_scanlines_aa(rasterizer, sl, renb, sa, sg); + } + else + agg::render_scanlines_aa(rasterizer, scanline_p, renb, sa, sg); + rasterizer.reset(); + inpath = false; + return *this; +} +#endif SDraw& SDraw::Fill(const Image& image, double x1, double y1, double x2, double y2, dword flags) { diff --git a/uppdev/SDraw/Gradient.cpp b/uppdev/SDraw/Gradient.cpp index 281fb1839..a645e03a2 100644 --- a/uppdev/SDraw/Gradient.cpp +++ b/uppdev/SDraw/Gradient.cpp @@ -2,17 +2,39 @@ NAMESPACE_UPP -Image Gradient::Generate(int cx) const +SDraw& SDraw::ColorStop(double pos, const RGBA& color) +{ + Attr& a = Cttr(); + pos = minmax(pos, 0.0, 1.0); + int i = FindLowerBound(a.stop, pos); + a.stop.Insert(i, pos); + a.stop_color.Insert(i, color); + return *this; +} + +SDraw& SDraw::ClearStops() +{ + Attr& a = Cttr(); + a.stop.Clear(); + a.stop_color.Clear(); + return *this; +} + +void SDraw::MakeGradient(RGBA *t, RGBA color1, RGBA color2, int cx) { - RTIMING("Gradient"); - ImageBuffer ib(cx, 1); - RGBA *t = ~ib; - cx--; int l = 0; - RGBA cl = color[0]; - for(int i = 0; i < pos.GetCount() - 1; i++) { - int h = (int)(pos[i + 1] * cx); - RGBA ch = color[i + 1]; + RGBA cl = color1; + for(int i = 0; i <= pathattr.stop.GetCount(); i++) { + int h; + RGBA ch; + if(i < pathattr.stop.GetCount()) { + h = (int)(pathattr.stop[i] * (cx - 1)); + ch = pathattr.stop_color[i]; + } + else { + h = cx - 1; + ch = color2; + } int w = h - l; for(int j = 0; j < w; j++) { t->r = ((w - j) * cl.r + j * ch.r) / w; @@ -25,31 +47,17 @@ Image Gradient::Generate(int cx) const l = h; } *t = cl; - return ib; } -Gradient& Gradient::Stop(double p, RGBA c) +SDraw& SDraw::Fill(double x1, double y1, const RGBA& color1, + double x2, double y2, const RGBA& color2, int style) { - int i = FindLowerBound(pos, p); - pos.Insert(i, p); - color.Insert(i, c); + ImageBuffer ib(2048, 1); // adapt size according to bound rect + MakeGradient(ib, color1, color2, 2048); + Fill(ib, x1, y1, x2, y2, FILL_VPAD | FILL_FAST | + (style == GRADIENT_PAD ? FILL_HPAD : style == GRADIENT_REPEAT + ? FILL_HREPEAT : FILL_HREFLECT)); return *this; } -Gradient::Gradient(RGBA c1, RGBA c2) -{ - pos.Add(0); - color.Add(c1); - pos.Add(1.0); - color.Add(c2); -} - -SDraw& SDraw::Fill(const Gradient& gradient, double x1, double y1, double x2, double y2, - dword flags) -{ - Image m = gradient.Generate(256); - Fill(m, x1, y1, x2, y2, FILL_HCOPY|FILL_REPEAT); - return *this; -} - -END_UPP_NAMESPACE \ No newline at end of file +END_UPP_NAMESPACE diff --git a/uppdev/SDraw/RadialGradient.cpp b/uppdev/SDraw/RadialGradient.cpp new file mode 100644 index 000000000..7cb0830fe --- /dev/null +++ b/uppdev/SDraw/RadialGradient.cpp @@ -0,0 +1,216 @@ +#include "SDraw.h" + +NAMESPACE_UPP + +uint16 g_sqrt_table[1024] = //----------g_sqrt_table +{ + 0, + 2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444, + 8689,8927,9159,9385,9606,9822,10033,10240,10443,10642,10837,11029,11217,11403,11585, + 11765,11942,12116,12288,12457,12625,12790,12953,13114,13273,13430,13585,13738,13890, + 14040,14189,14336,14482,14626,14768,14910,15050,15188,15326,15462,15597,15731,15864, + 15995,16126,16255,16384,16512,16638,16764,16888,17012,17135,17257,17378,17498,17618, + 17736,17854,17971,18087,18203,18318,18432,18545,18658,18770,18882,18992,19102,19212, + 19321,19429,19537,19644,19750,19856,19961,20066,20170,20274,20377,20480,20582,20684, + 20785,20886,20986,21085,21185,21283,21382,21480,21577,21674,21771,21867,21962,22058, + 22153,22247,22341,22435,22528,22621,22713,22806,22897,22989,23080,23170,23261,23351, + 23440,23530,23619,23707,23796,23884,23971,24059,24146,24232,24319,24405,24491,24576, + 24661,24746,24831,24915,24999,25083,25166,25249,25332,25415,25497,25580,25661,25743, + 25824,25905,25986,26067,26147,26227,26307,26387,26466,26545,26624,26703,26781,26859, + 26937,27015,27092,27170,27247,27324,27400,27477,27553,27629,27705,27780,27856,27931, + 28006,28081,28155,28230,28304,28378,28452,28525,28599,28672,28745,28818,28891,28963, + 29035,29108,29180,29251,29323,29394,29466,29537,29608,29678,29749,29819,29890,29960, + 30030,30099,30169,30238,30308,30377,30446,30515,30583,30652,30720,30788,30856,30924, + 30992,31059,31127,31194,31261,31328,31395,31462,31529,31595,31661,31727,31794,31859, + 31925,31991,32056,32122,32187,32252,32317,32382,32446,32511,32575,32640,32704,32768, + 32832,32896,32959,33023,33086,33150,33213,33276,33339,33402,33465,33527,33590,33652, + 33714,33776,33839,33900,33962,34024,34086,34147,34208,34270,34331,34392,34453,34514, + 34574,34635,34695,34756,34816,34876,34936,34996,35056,35116,35176,35235,35295,35354, + 35413,35472,35531,35590,35649,35708,35767,35825,35884,35942,36001,36059,36117,36175, + 36233,36291,36348,36406,36464,36521,36578,36636,36693,36750,36807,36864,36921,36978, + 37034,37091,37147,37204,37260,37316,37372,37429,37485,37540,37596,37652,37708,37763, + 37819,37874,37929,37985,38040,38095,38150,38205,38260,38315,38369,38424,38478,38533, + 38587,38642,38696,38750,38804,38858,38912,38966,39020,39073,39127,39181,39234,39287, + 39341,39394,39447,39500,39553,39606,39659,39712,39765,39818,39870,39923,39975,40028, + 40080,40132,40185,40237,40289,40341,40393,40445,40497,40548,40600,40652,40703,40755, + 40806,40857,40909,40960,41011,41062,41113,41164,41215,41266,41317,41368,41418,41469, + 41519,41570,41620,41671,41721,41771,41821,41871,41922,41972,42021,42071,42121,42171, + 42221,42270,42320,42369,42419,42468,42518,42567,42616,42665,42714,42763,42813,42861, + 42910,42959,43008,43057,43105,43154,43203,43251,43300,43348,43396,43445,43493,43541, + 43589,43637,43685,43733,43781,43829,43877,43925,43972,44020,44068,44115,44163,44210, + 44258,44305,44352,44400,44447,44494,44541,44588,44635,44682,44729,44776,44823,44869, + 44916,44963,45009,45056,45103,45149,45195,45242,45288,45334,45381,45427,45473,45519, + 45565,45611,45657,45703,45749,45795,45840,45886,45932,45977,46023,46069,46114,46160, + 46205,46250,46296,46341,46386,46431,46477,46522,46567,46612,46657,46702,46746,46791, + 46836,46881,46926,46970,47015,47059,47104,47149,47193,47237,47282,47326,47370,47415, + 47459,47503,47547,47591,47635,47679,47723,47767,47811,47855,47899,47942,47986,48030, + 48074,48117,48161,48204,48248,48291,48335,48378,48421,48465,48508,48551,48594,48637, + 48680,48723,48766,48809,48852,48895,48938,48981,49024,49067,49109,49152,49195,49237, + 49280,49322,49365,49407,49450,49492,49535,49577,49619,49661,49704,49746,49788,49830, + 49872,49914,49956,49998,50040,50082,50124,50166,50207,50249,50291,50332,50374,50416, + 50457,50499,50540,50582,50623,50665,50706,50747,50789,50830,50871,50912,50954,50995, + 51036,51077,51118,51159,51200,51241,51282,51323,51364,51404,51445,51486,51527,51567, + 51608,51649,51689,51730,51770,51811,51851,51892,51932,51972,52013,52053,52093,52134, + 52174,52214,52254,52294,52334,52374,52414,52454,52494,52534,52574,52614,52654,52694, + 52734,52773,52813,52853,52892,52932,52972,53011,53051,53090,53130,53169,53209,53248, + 53287,53327,53366,53405,53445,53484,53523,53562,53601,53640,53679,53719,53758,53797, + 53836,53874,53913,53952,53991,54030,54069,54108,54146,54185,54224,54262,54301,54340, + 54378,54417,54455,54494,54532,54571,54609,54647,54686,54724,54762,54801,54839,54877, + 54915,54954,54992,55030,55068,55106,55144,55182,55220,55258,55296,55334,55372,55410, + 55447,55485,55523,55561,55599,55636,55674,55712,55749,55787,55824,55862,55900,55937, + 55975,56012,56049,56087,56124,56162,56199,56236,56273,56311,56348,56385,56422,56459, + 56497,56534,56571,56608,56645,56682,56719,56756,56793,56830,56867,56903,56940,56977, + 57014,57051,57087,57124,57161,57198,57234,57271,57307,57344,57381,57417,57454,57490, + 57527,57563,57599,57636,57672,57709,57745,57781,57817,57854,57890,57926,57962,57999, + 58035,58071,58107,58143,58179,58215,58251,58287,58323,58359,58395,58431,58467,58503, + 58538,58574,58610,58646,58682,58717,58753,58789,58824,58860,58896,58931,58967,59002, + 59038,59073,59109,59144,59180,59215,59251,59286,59321,59357,59392,59427,59463,59498, + 59533,59568,59603,59639,59674,59709,59744,59779,59814,59849,59884,59919,59954,59989, + 60024,60059,60094,60129,60164,60199,60233,60268,60303,60338,60373,60407,60442,60477, + 60511,60546,60581,60615,60650,60684,60719,60753,60788,60822,60857,60891,60926,60960, + 60995,61029,61063,61098,61132,61166,61201,61235,61269,61303,61338,61372,61406,61440, + 61474,61508,61542,61576,61610,61644,61678,61712,61746,61780,61814,61848,61882,61916, + 61950,61984,62018,62051,62085,62119,62153,62186,62220,62254,62287,62321,62355,62388, + 62422,62456,62489,62523,62556,62590,62623,62657,62690,62724,62757,62790,62824,62857, + 62891,62924,62957,62991,63024,63057,63090,63124,63157,63190,63223,63256,63289,63323, + 63356,63389,63422,63455,63488,63521,63554,63587,63620,63653,63686,63719,63752,63785, + 63817,63850,63883,63916,63949,63982,64014,64047,64080,64113,64145,64178,64211,64243, + 64276,64309,64341,64374,64406,64439,64471,64504,64536,64569,64601,64634,64666,64699, + 64731,64763,64796,64828,64861,64893,64925,64957,64990,65022,65054,65086,65119,65151, + 65183,65215,65247,65279,65312,65344,65376,65408,65440,65472,65504 +}; + + +int8 g_elder_bit_table[256] = //---------g_elder_bit_table +{ + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + +unsigned fastint_sqrt(unsigned val) +{ + unsigned t = val; + int bit=0; + unsigned shift = 11; + bit = t >> 24; + if(bit) + bit = g_elder_bit_table[bit] + 24; + else { + bit = (t >> 16) & 0xFF; + if(bit) + bit = g_elder_bit_table[bit] + 16; + else { + bit = (t >> 8) & 0xFF; + if(bit) + bit = g_elder_bit_table[bit] + 8; + else + bit = g_elder_bit_table[t]; + } + } + bit -= 9; + if(bit > 0) { + bit = (bit >> 1) + (bit & 1); + shift -= bit; + val >>= (bit << 1); + } + return g_sqrt_table[val] >> shift; +} + +struct UppRadialSpan { + agg::span_interpolator_linear<> interpolator; + int cx, cy, r, fx, fy; + int style; + int alpha; + RGBA gradient[2048]; + + void SetAlpha(int a) { alpha = a + (a >> 7); } + + void prepare() {} + + void generate(agg::rgba8 *_span, int x, int y, unsigned len) { + interpolator.begin(x + 0.5, y + 0.5, len); + RGBA *span = (RGBA *)_span; + bool focus = cx != fx || cy != fy; + while(len--) { + int x; + int y; + interpolator.coordinates(&x, &y); + x >>= 2; + y >>= 2; + int dc = Upp::fastint_sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)); + RGBA v; + if(dc < r) { + if(focus) { + int df = Upp::fastint_sqrt((x - fx) * (x - fx) + (y - fy) * (y - fy)); + v = gradient[minmax(2047 * df / (r - dc + df), 0, 2047)]; + } + else + v = gradient[minmax(2047 * dc / r, 0, 2047)]; + } + else + v = gradient[2047]; + if(alpha == 256) + *span = v; + else { + span->r = byte((alpha * v.r) >> 8); + span->g = byte((alpha * v.g) >> 8); + span->b = byte((alpha * v.b) >> 8); + span->a = byte((alpha * v.a) >> 8); + } + ++span; + ++interpolator; + } + } +}; + +SDraw& SDraw::Fill(double x1, double y1, double r, double fx, double fy, const RGBA& color1, const RGBA& color2, int style) +{ + if(inpath) + path.close_polygon(); + span_alloc sa; + Matrix2D m = pathattr.mtx; + m.invert(); + UppRadialSpan sg; + sg.interpolator.transformer(m); + sg.SetAlpha(int(pathattr.opacity * 255)); + sg.style = style; +// pathattr.mtx.Transform(x1, y1); + sg.cx = (int)x1 << 6; + sg.cy = (int)y1 << 6; +// pathattr.mtx.Transform(fx, fy); + sg.fx = (int)fx << 6; + sg.fy = (int)fy << 6; +// pathattr.mtx.Transform(r, fx); // ??! + sg.r = (int)r << 6; + MakeGradient(sg.gradient, color1, color2, 2048); + + rasterizer.reset(); + rasterizer.filling_rule(pathattr.evenodd ? agg::fill_even_odd : agg::fill_non_zero); + rasterizer.add_path(curved_trans); + + if(clip.GetCount()) { + agg::rendering_buffer mask_rbuf; + mask_rbuf.attach(~clip.Top(), size.cx, size.cy, size.cx); + agg::alpha_mask_gray8 mask(mask_rbuf); + agg::scanline_u8_am sl(mask); + agg::render_scanlines_aa(rasterizer, sl, renb, sa, sg); + } + else + agg::render_scanlines_aa(rasterizer, scanline_p, renb, sa, sg); + rasterizer.reset(); + inpath = false; + return *this; +} + +SDraw& SDraw::Fill(double x1, double y1, double r, const RGBA& color1, const RGBA& color2, int style) +{ + return Fill(x1, y1, r, x1, y1, color1, color2, style); +} + +END_UPP_NAMESPACE diff --git a/uppdev/SDraw/SDraw.cpp b/uppdev/SDraw/SDraw.cpp index 396009dc0..9004aa671 100644 --- a/uppdev/SDraw/SDraw.cpp +++ b/uppdev/SDraw/SDraw.cpp @@ -4,7 +4,7 @@ NAMESPACE_UPP #define LTIMING(x) RTIMING(x) -void SDraw::PathPoint(double x, double y) +inline void SDraw::PathPoint(double x, double y) { if(inpath) { pathrect.left = min(pathrect.left, x); @@ -38,6 +38,7 @@ SDraw& SDraw::Move(double x, double y) SDraw& SDraw::Line(double x, double y) { + control = current; PathPoint(x, y); path.line_to(x, y); inpath = true; @@ -143,7 +144,10 @@ void SDraw::End() clip.SetCount(attr.cliplevel); } -void SDraw::Transform(const Matrix2D& m) { Cttr().mtx = m * attr.mtx; } +void SDraw::Transform(const Matrix2D& m) +{ + Cttr().mtx = m * attr.mtx; +} SDraw& SDraw::Opacity(double o) { Cttr().opacity *= o; return *this; } SDraw& SDraw::LineCap(int linecap) { Cttr().cap = linecap; return *this; } @@ -184,7 +188,6 @@ SDraw::SDraw(ImageBuffer& ib) { size = ib.GetSize(); sizef = size; - UPP::Fill(~buffer, White(), buffer.GetLength()); //!!! rbuf.attach((agg::int8u *)~buffer, size.cx, size.cy, size.cx * 4); pixf.attach(rbuf); renb.attach(pixf); diff --git a/uppdev/SDraw/SDraw.h b/uppdev/SDraw/SDraw.h index 32c9acd05..4d1dff63e 100644 --- a/uppdev/SDraw/SDraw.h +++ b/uppdev/SDraw/SDraw.h @@ -51,22 +51,25 @@ enum { LINEJOIN_ROUND = agg::round_join, LINEJOIN_BEVEL = agg::bevel_join, - FILL_NONE = 0, - FILL_PAD = 1, - FILL_REPEAT = 2, - FILL_REFLECT = 3, - FILL_HCOPY = 4, - FILL_VCOPY = 8, -}; + FILL_EXACT = 0, -class Gradient { - Vector pos; - Vector color; + FILL_HPAD = 1, + FILL_HREPEAT = 2, + FILL_HREFLECT = 3, -public: - Image Generate(int w) const; - Gradient& Stop(double pos, RGBA c); - Gradient(RGBA c1, RGBA c2); + FILL_VPAD = 4, + FILL_VREPEAT = 8, + FILL_VREFLECT = 12, + + FILL_PAD = FILL_HPAD|FILL_VPAD, + FILL_REPEAT = FILL_HREPEAT|FILL_VREPEAT, + FILL_REFLECT = FILL_HREFLECT|FILL_VREFLECT, + + FILL_FAST = 256, + + GRADIENT_PAD = 0, + GRADIENT_REPEAT = 1, + GRADIENT_REFLECT = 2, }; class SDraw : public Draw { @@ -163,6 +166,8 @@ private: byte cap; double miter_limit; WithDeepCopy< Vector > dash; + WithDeepCopy< Vector > stop; + WithDeepCopy< Vector > stop_color; double dash_start; double opacity; int cliplevel; @@ -205,6 +210,7 @@ private: void RenderClip(byte *t, int alpha); void RectPath(const Rect& r); void RectPath(int x, int y, int cx, int cy); + void MakeGradient(RGBA *t, RGBA color1, RGBA color2, int cx); public: SDraw& Move(double x, double y); @@ -215,13 +221,20 @@ public: SDraw& Cubic(double x2, double y2, double x, double y); SDraw& Close(); - SDraw& Fill(const RGBA& rgba); + SDraw& Fill(const RGBA& color); SDraw& Fill(const Image& image, const Matrix2D& transsrc = Matrix2D(), dword flags = 0); SDraw& Fill(const Image& image, double x1, double y1, double x2, double y2, dword flags = 0); - SDraw& Fill(const Gradient& gradient, double x1, double y1, double x2, double y2, - dword flags = FILL_PAD); + SDraw& Fill(double x1, double y1, const RGBA& color1, + double x2, double y2, const RGBA& color2, + int style = GRADIENT_PAD); + SDraw& Fill(double x1, double y1, double r, double fx, double fy, + const RGBA& color1, const RGBA& color2, + int style = GRADIENT_PAD); + SDraw& Fill(double x1, double y1, double r, + const RGBA& color1, const RGBA& color2, + int style = GRADIENT_PAD); SDraw& Stroke(double width, const RGBA& rgba); SDraw& Stroke(double width, const Image& image, const Matrix2D& transsrc, dword flags = 0); @@ -240,6 +253,9 @@ public: SDraw& Path(CParser& p); SDraw& Path(const char *path); + SDraw& ColorStop(double pos, const RGBA& color); + SDraw& ClearStops(); + SDraw& Opacity(double o); SDraw& LineCap(int linecap); SDraw& LineJoin(int linejoin); diff --git a/uppdev/SDraw/SDraw.upp b/uppdev/SDraw/SDraw.upp index c048c1a36..a7dfd6b23 100644 --- a/uppdev/SDraw/SDraw.upp +++ b/uppdev/SDraw/SDraw.upp @@ -8,6 +8,7 @@ file Stroke.cpp, Clip.cpp, Gradient.cpp, + RadialGradient.cpp, FontX11.cpp, FontWin32.cpp, Arc.cpp, diff --git a/uppdev/SDraw/agg_span_image_filter_upp.h b/uppdev/SDraw/agg_span_image_filter_upp.h index 6d6db155e..4d2276112 100644 --- a/uppdev/SDraw/agg_span_image_filter_upp.h +++ b/uppdev/SDraw/agg_span_image_filter_upp.h @@ -202,6 +202,37 @@ namespace agg base_mask = color_type::base_mask }; + int ax, ay, cx, cy, maxx, maxy; + bool hreflect, vreflect; + bool hrepeat, vrepeat; + bool hcopy, vcopy; + + void AdjustX(int& x_lr) { + if(hcopy) { + if(x_lr > maxx) + x_lr = maxx; + if(x_lr < 0) + x_lr = 0; + } + if(hreflect) + x_lr = (x_lr + ax) / cx & 1 ? (ax - x_lr - 1) % cx : (x_lr + ax) % cx; + if(hrepeat) + x_lr = (x_lr + ax) % cx; + } + + void AdjustY(int& y_lr) { + if(vcopy) { + if(y_lr > maxy) + y_lr = maxy; + if(y_lr < 0) + y_lr = 0; + } + if(vreflect) + y_lr = (y_lr + ay) / cy & 1 ? (ay - y_lr - 1) % cy : (y_lr + ay) % cy; + if(vrepeat) + y_lr = (y_lr + ay) % cy; + } + //-------------------------------------------------------------------- span_image_filter_rgba_bilinear_clip() { alpha = 256; @@ -214,15 +245,11 @@ namespace agg m_back_color(back_color) { m_alpha = 256; - m_tile = false; - m_vcopy = m_hcopy = false; + hreflect = hrepeat = vreflect = vrepeat = hcopy = vcopy = false; } const color_type& background_color() const { return m_back_color; } void background_color(const color_type& v) { m_back_color = v; } void alpha(int a) { m_alpha = a + (a >> 7); } - void tile(bool b) { m_tile = b; } - void vcopy() { m_vcopy = true; } - void hcopy() { m_hcopy = true; } //-------------------------------------------------------------------- void generate(color_type* span, int x, int y, unsigned len) @@ -237,15 +264,15 @@ namespace agg value_type back_a = m_back_color.a; const value_type *fg_ptr; - int cx = base_type::source().width(); - int cy = base_type::source().height(); - int maxx = base_type::source().width() - 1; - int maxy = base_type::source().height() - 1; - int ax, ay; - if(m_tile) { - ax = 60000 / cx * cx; - ay = 60000 / cy * cy; - } + cx = base_type::source().width(); + cy = base_type::source().height(); + maxx = base_type::source().width() - 1; + maxy = base_type::source().height() - 1; + + if(hreflect || hrepeat) + ax = 6000000 / cx * cx; + if(vreflect || vrepeat) + ay = 6000000 / cy * cy; do { @@ -262,24 +289,8 @@ namespace agg unsigned weight; - if(m_hcopy) { - if(x_lr > maxx) - x_lr = maxx; - if(x_lr < 0) - x_lr = 0; - } - - if(m_vcopy) { - if(y_lr > maxy) - y_lr = maxy; - if(y_lr < 0) - y_lr = 0; - } - - if(m_tile) { //AGGUPP - x_lr = (x_lr + ax) % cx; - y_lr = (y_lr + ay) % cy; - } + AdjustX(x_lr); + AdjustY(y_lr); if(x_lr >= 0 && y_lr >= 0 && x_lr < maxx && y_lr < maxy) @@ -331,8 +342,10 @@ namespace agg } else { - if((x_lr < -1 || x_lr > maxx) && !m_hcopy || - (y_lr > maxy || y_lr < -1) && !m_vcopy) + int x0 = x_lr; + int y0 = y_lr; + if((x_lr < -1 || x_lr > maxx) && !hcopy || + (y_lr > maxy || y_lr < -1) && !vcopy) { fg[order_type::R] = back_r; fg[order_type::G] = back_g; @@ -369,14 +382,9 @@ namespace agg fg[order_type::B] += back_b * weight; fg[order_type::A] += back_a * weight; } - - x_lr++; - if(m_hcopy && x_lr > maxx) - x_lr = maxx; - - if(m_tile) //AGGUPP - x_lr = (x_lr + ax) % cx; + x_lr = x0 + 1; + AdjustX(x_lr); weight = x_hr * (image_subpixel_scale - y_hr); if(x_lr >= 0 && y_lr >= 0 && @@ -398,16 +406,12 @@ namespace agg fg[order_type::A] += back_a * weight; } - if(!m_hcopy) - x_lr--; - y_lr++; - if(m_vcopy) - y_lr = maxy; - - if(m_tile) { //AGGUPP - x_lr = (x_lr + ax) % cx; - y_lr = (y_lr + ay) % cy; - } + if(!hcopy) { + x_lr = x0; + AdjustX(x_lr); + } + y_lr = y0 + 1; + AdjustY(y_lr); weight = (image_subpixel_scale - x_hr) * y_hr; if(x_lr >= 0 && y_lr >= 0 && @@ -429,11 +433,8 @@ namespace agg fg[order_type::A] += back_a * weight; } - x_lr++; - if(m_hcopy && x_lr > maxx) - x_lr = maxx; - if(m_tile) //AGGUPP - x_lr = (x_lr + ax) % cx; + x_lr = x0 + 1; + AdjustX(x_lr); weight = x_hr * y_hr; if(x_lr >= 0 && y_lr >= 0 && @@ -462,10 +463,18 @@ namespace agg } } - span->r = (m_alpha * (value_type)fg[order_type::R]) >> 8; //AGGUPP - span->g = (m_alpha * (value_type)fg[order_type::G]) >> 8; - span->b = (m_alpha * (value_type)fg[order_type::B]) >> 8; - span->a = (m_alpha * (value_type)fg[order_type::A]) >> 8; + if(m_alpha == 255) {// AGGUPP + span->r = fg[order_type::R]; + span->g = fg[order_type::G]; + span->b = fg[order_type::B]; + span->a = fg[order_type::A]; + } + else { + span->r = (m_alpha * (value_type)fg[order_type::R]) >> 8; //AGGUPP + span->g = (m_alpha * (value_type)fg[order_type::G]) >> 8; + span->b = (m_alpha * (value_type)fg[order_type::B]) >> 8; + span->a = (m_alpha * (value_type)fg[order_type::A]) >> 8; + } ++span; ++base_type::interpolator(); @@ -474,7 +483,6 @@ namespace agg private: color_type m_back_color; int m_alpha; - bool m_tile, m_hcopy, m_vcopy; }; diff --git a/uppdev/SDrawTest/main.cpp b/uppdev/SDrawTest/main.cpp index f38786531..b18ca1ac6 100644 --- a/uppdev/SDrawTest/main.cpp +++ b/uppdev/SDrawTest/main.cpp @@ -372,10 +372,10 @@ void PaintExample(SDraw& sw) .Stroke(35, Black()) .Stroke(30, TestImg::test(), m, true); */ - sw.Text(1000, 50, "HELLO WORLD!", Arial(300).Bold()) - .Fill(Gradient(50 * Blue(), Red()).Stop(0.4, Green()), - 1000, 0, GetTextSize("HELLO WORLD!", Arial(300).Bold()).cx - 100, 0, - 0); +// sw.Text(1000, 50, "HELLO WORLD!", Arial(300).Bold()) +// .Fill(Gradient(50 * Blue(), Red()).Stop(0.4, Green()), +// 1000, 0, GetTextSize("HELLO WORLD!", Arial(300).Bold()).cx - 100, 0, +// 0); if(0) { for(int h = 0; h < 3; h++) { @@ -383,18 +383,18 @@ void PaintExample(SDraw& sw) sw.Translate(500 * h, 300 * h); double q = h * 0.2 + 1; sw.Move(0, 0).Line(1600, 0).Line(1600, 1600).Line(0, 1600) - .Fill(TestImg::test(), q * 300, 300, q * 600, 300, 0 * FILL_REPEAT); + .Fill(TestImg::test(), q * 300, 300, q * 600, 300, 0 * FILL_HREPEAT); sw.Move(q * 300, 300).Line(q * 600, 300).Line(q * 600, 600).Line(q * 300, 600).Close().Stroke(1, LtRed()); sw.End(); } sw.Move(0, 0).Line(3000, 0).Line(3000, 3000).Line(0, 3000) - .Fill(TestImg::test(), 1500, 300, 1500, 600, 0 * FILL_REPEAT); + .Fill(TestImg::test(), 1500, 300, 1500, 600, 0 * FILL_HREPEAT); sw.Move(0, 0).Line(1600, 0).Line(1600, 1600).Line(0, 1600) - .Fill(TestImg::test(), 700, 600, 800, 100, 0 * FILL_REPEAT); + .Fill(TestImg::test(), 700, 600, 800, 100, 0 * FILL_VREPEAT); } sw.Path("M153 334 C153 334 151 334 151 334 C151 339 153 344 156 344 C164 344 171 339 171 334 " @@ -403,11 +403,39 @@ void PaintExample(SDraw& sw) "C111 361 131 384 156 384 C186 384 211 361 211 334 C211 300 186 274 156 274 ") .Stroke(2, Red()); sw.Path("M500,500 L600,500 L550,600").Fill(Black()).Stroke(2, LtRed()); - -// sw.Move(0, 0).Line(3000, 0).Line(3000, 3000).Line(0, 3000) -// .Fill(TestImg::test(), 500, 500, 1500, 500, FILL_VCOPY|FILL_HCOPY|FILL_REPEAT); } +unsigned fast_sqrt(unsigned val); + +/* +void RadialGradient(ImageBuffer& ib, int cx, int cy, int r, RGBA c1, RGBA c2, int fx, int fy) +{ + Size sz = ib.GetSize(); + RGBA *t = ib; + for(int y = 0; y < sz.cy; y++) + for(int x = 0; x < sz.cx; x++) { + int dc = fast_sqrt((x - cx) * (x - cx) + (y - cy) * (y - cy)); + if(dc < r) { + int df = fast_sqrt((x - fx) * (x - fx) + (y - fy) * (y - fy)); + int d = 256 * df / (r - dc + df); + + // int d = dc * (dc / r) + df * (r - dc) / r; + // d = dc * df / + // d = d % r; + // d = (d / r & 1) ? d % r : (1000 * r - d) % r; + if(dc <= r) { + t->r = ((256 - d) * c1.r + d * c2.r) >> 8; + t->g = ((256 - d) * c1.g + d * c2.g) >> 8; + t->b = ((256 - d) * c1.b + d * c2.b) >> 8; + t->a = ((256 - d) * c1.a + d * c2.a) >> 8; + } + } + else + *t = c2; + t++; + } +} +*/ struct App : TopWindow { Point p; @@ -421,10 +449,59 @@ struct App : TopWindow { Size sz = GetSize(); ImageBuffer ib(sz); Fill(~ib, White(), ib.GetLength()); + +// RadialGradient(ib, 200, 200, 100, White(), Blue(), 150, 160); + + SDraw sw(ib); - sw.Scale(0.3); -// sw.Rotate(0.01 * p.y - M_PI); - PaintExample(sw); + sw.Translate(300, 300); + sw.Scale(0.01 * p.x); + +// sw.Text(0, 0, "HELLO WORLD!", Arial(300).Bold()) +// .Fill(Gradient(50 * Blue(), Red()).Stop(0.4, Green()), +// 1000, 0, 1500, 0, GRADIENT_REFLECT); + + sw.Rotate(0.01 * p.y - M_PI); +// sw.Text(500, 200, "Hello world!", Arial(400)).Fill(Black()) +// .Fill(Gradient(100 * Cyan(), LtRed()).Stop(0.3, Green()), 520, 500, 570, 500); + +#if 0 + sw.Move(0, 0).Line(3000, 0).Line(3000, 3000).Line(0, 3000) + .Fill(TestImg::test(), 800, 500, 1800, 800, 0 + |FILL_PAD + |FILL_REPEAT + |FILL_FAST + |FILL_HREPEAT|FILL_VREFLECT + ); +#endif +// sw.Text(500, 50, "HELLO WORLD!", Arial(300).Bold()) +// .ColorStop(0.4, Green()) +// .Fill(1000, 0, 50 * Blue(), 1500, 0, Red(), GRADIENT_REFLECT); + +// sw.Arc(230, 200, 110, 100, 0, 2 * M_PI) + //.Fill((230 - 110) * 0.2, (200 - 100) * 0.4, 100, 110, 100, +// Color(200, 200, 200), Color(0, 0, 255)); + +// sw.Move(0, 0).Line(3000, 0).Line(3000, 3000).Line(0, 3000) + + // sw.Opacity(0.5); + +// sw.Arc(200, 200, 100, 100, 0, M_2PI) +// .ColorStop(0.2, LtRed()) +// .ColorStop(0.7, Yellow()) +// .Fill(200, 200, 100, p.x, p.y, White(), Blue()); +// .Fill(200, 200, 100, 150, 160, White(), Blue()); + + sw.Arc(200, 200, 100, 100, 0, M_2PI) + .Fill(200, 200, 100, 150, 160, White(), Blue()) + ; + sw.Arc(200, 200, 100, 100, 0, M_2PI) + .Opacity(0.6) + .Fill(100, 200, LtRed(), 300, 200, Blue()) + ; + + +// PaintExample(sw); sw.Rotate(0.05); // sw.Opacity(0.5); // PaintExample(sw); @@ -447,9 +524,43 @@ struct App : TopWindow { }; +void BenchmarkImageFill() +{ + ImageBuffer ib(1000, 1000); + Fill(~ib, White(), ib.GetLength()); + SDraw sw(ib); + for(int i = 0; i < 10 * 0; i++) { + RTIMING("BenchmarkImageFill FILL_HREPEAT|FILL_VREFLECT"); + sw.Move(0, 0).Line(3000, 0).Line(3000, 3000).Line(0, 3000) + .Fill(TestImg::test(), 800, 500, 1800, 800 + , FILL_HREPEAT|FILL_VREFLECT + ); + } + for(int i = 0; i < 10 * 0; i++) { + RTIMING("BenchmarkImageFill FILL_EXACT"); + sw.Move(0, 0).Line(3000, 0).Line(3000, 3000).Line(0, 3000) + .Fill(TestImg::test(), 800, 500, 1800, 800 + ); + } + for(int i = 0; i < 10 * 0; i++) { + RTIMING("BenchmarkImageFill FILL_PAD"); + sw.Move(0, 0).Line(3000, 0).Line(3000, 3000).Line(0, 3000) + .Fill(TestImg::test(), 800, 500, 1800, 800, FILL_PAD); + } + for(int i = 0; i < 10 * 1; i++) { + RTIMING("BenchmarkImageFill FILL_REPEAT"); + sw.Move(0, 0).Line(3000, 0).Line(3000, 3000).Line(0, 3000) + .Fill(TestImg::test(), 800, 500, 1800, 800, FILL_REPEAT); + } +} + + GUI_APP_MAIN { SetDefaultCharset(CHARSET_WIN1250); + +// BenchmarkImageFill(); + #ifndef _DEBUG ImageBuffer ib(500, 500); for(int i = 0; i < 0; i++) { diff --git a/uppdev/bsr/bsr.cpp b/uppdev/bsr/bsr.cpp new file mode 100644 index 000000000..ec1e627a2 --- /dev/null +++ b/uppdev/bsr/bsr.cpp @@ -0,0 +1,220 @@ +#include + +using namespace Upp; + +#pragma intrinsic(_BitScanForward) + +uint16 g_sqrt_table[1024] = //----------g_sqrt_table +{ + 0, + 2048,2896,3547,4096,4579,5017,5418,5793,6144,6476,6792,7094,7384,7663,7932,8192,8444, + 8689,8927,9159,9385,9606,9822,10033,10240,10443,10642,10837,11029,11217,11403,11585, + 11765,11942,12116,12288,12457,12625,12790,12953,13114,13273,13430,13585,13738,13890, + 14040,14189,14336,14482,14626,14768,14910,15050,15188,15326,15462,15597,15731,15864, + 15995,16126,16255,16384,16512,16638,16764,16888,17012,17135,17257,17378,17498,17618, + 17736,17854,17971,18087,18203,18318,18432,18545,18658,18770,18882,18992,19102,19212, + 19321,19429,19537,19644,19750,19856,19961,20066,20170,20274,20377,20480,20582,20684, + 20785,20886,20986,21085,21185,21283,21382,21480,21577,21674,21771,21867,21962,22058, + 22153,22247,22341,22435,22528,22621,22713,22806,22897,22989,23080,23170,23261,23351, + 23440,23530,23619,23707,23796,23884,23971,24059,24146,24232,24319,24405,24491,24576, + 24661,24746,24831,24915,24999,25083,25166,25249,25332,25415,25497,25580,25661,25743, + 25824,25905,25986,26067,26147,26227,26307,26387,26466,26545,26624,26703,26781,26859, + 26937,27015,27092,27170,27247,27324,27400,27477,27553,27629,27705,27780,27856,27931, + 28006,28081,28155,28230,28304,28378,28452,28525,28599,28672,28745,28818,28891,28963, + 29035,29108,29180,29251,29323,29394,29466,29537,29608,29678,29749,29819,29890,29960, + 30030,30099,30169,30238,30308,30377,30446,30515,30583,30652,30720,30788,30856,30924, + 30992,31059,31127,31194,31261,31328,31395,31462,31529,31595,31661,31727,31794,31859, + 31925,31991,32056,32122,32187,32252,32317,32382,32446,32511,32575,32640,32704,32768, + 32832,32896,32959,33023,33086,33150,33213,33276,33339,33402,33465,33527,33590,33652, + 33714,33776,33839,33900,33962,34024,34086,34147,34208,34270,34331,34392,34453,34514, + 34574,34635,34695,34756,34816,34876,34936,34996,35056,35116,35176,35235,35295,35354, + 35413,35472,35531,35590,35649,35708,35767,35825,35884,35942,36001,36059,36117,36175, + 36233,36291,36348,36406,36464,36521,36578,36636,36693,36750,36807,36864,36921,36978, + 37034,37091,37147,37204,37260,37316,37372,37429,37485,37540,37596,37652,37708,37763, + 37819,37874,37929,37985,38040,38095,38150,38205,38260,38315,38369,38424,38478,38533, + 38587,38642,38696,38750,38804,38858,38912,38966,39020,39073,39127,39181,39234,39287, + 39341,39394,39447,39500,39553,39606,39659,39712,39765,39818,39870,39923,39975,40028, + 40080,40132,40185,40237,40289,40341,40393,40445,40497,40548,40600,40652,40703,40755, + 40806,40857,40909,40960,41011,41062,41113,41164,41215,41266,41317,41368,41418,41469, + 41519,41570,41620,41671,41721,41771,41821,41871,41922,41972,42021,42071,42121,42171, + 42221,42270,42320,42369,42419,42468,42518,42567,42616,42665,42714,42763,42813,42861, + 42910,42959,43008,43057,43105,43154,43203,43251,43300,43348,43396,43445,43493,43541, + 43589,43637,43685,43733,43781,43829,43877,43925,43972,44020,44068,44115,44163,44210, + 44258,44305,44352,44400,44447,44494,44541,44588,44635,44682,44729,44776,44823,44869, + 44916,44963,45009,45056,45103,45149,45195,45242,45288,45334,45381,45427,45473,45519, + 45565,45611,45657,45703,45749,45795,45840,45886,45932,45977,46023,46069,46114,46160, + 46205,46250,46296,46341,46386,46431,46477,46522,46567,46612,46657,46702,46746,46791, + 46836,46881,46926,46970,47015,47059,47104,47149,47193,47237,47282,47326,47370,47415, + 47459,47503,47547,47591,47635,47679,47723,47767,47811,47855,47899,47942,47986,48030, + 48074,48117,48161,48204,48248,48291,48335,48378,48421,48465,48508,48551,48594,48637, + 48680,48723,48766,48809,48852,48895,48938,48981,49024,49067,49109,49152,49195,49237, + 49280,49322,49365,49407,49450,49492,49535,49577,49619,49661,49704,49746,49788,49830, + 49872,49914,49956,49998,50040,50082,50124,50166,50207,50249,50291,50332,50374,50416, + 50457,50499,50540,50582,50623,50665,50706,50747,50789,50830,50871,50912,50954,50995, + 51036,51077,51118,51159,51200,51241,51282,51323,51364,51404,51445,51486,51527,51567, + 51608,51649,51689,51730,51770,51811,51851,51892,51932,51972,52013,52053,52093,52134, + 52174,52214,52254,52294,52334,52374,52414,52454,52494,52534,52574,52614,52654,52694, + 52734,52773,52813,52853,52892,52932,52972,53011,53051,53090,53130,53169,53209,53248, + 53287,53327,53366,53405,53445,53484,53523,53562,53601,53640,53679,53719,53758,53797, + 53836,53874,53913,53952,53991,54030,54069,54108,54146,54185,54224,54262,54301,54340, + 54378,54417,54455,54494,54532,54571,54609,54647,54686,54724,54762,54801,54839,54877, + 54915,54954,54992,55030,55068,55106,55144,55182,55220,55258,55296,55334,55372,55410, + 55447,55485,55523,55561,55599,55636,55674,55712,55749,55787,55824,55862,55900,55937, + 55975,56012,56049,56087,56124,56162,56199,56236,56273,56311,56348,56385,56422,56459, + 56497,56534,56571,56608,56645,56682,56719,56756,56793,56830,56867,56903,56940,56977, + 57014,57051,57087,57124,57161,57198,57234,57271,57307,57344,57381,57417,57454,57490, + 57527,57563,57599,57636,57672,57709,57745,57781,57817,57854,57890,57926,57962,57999, + 58035,58071,58107,58143,58179,58215,58251,58287,58323,58359,58395,58431,58467,58503, + 58538,58574,58610,58646,58682,58717,58753,58789,58824,58860,58896,58931,58967,59002, + 59038,59073,59109,59144,59180,59215,59251,59286,59321,59357,59392,59427,59463,59498, + 59533,59568,59603,59639,59674,59709,59744,59779,59814,59849,59884,59919,59954,59989, + 60024,60059,60094,60129,60164,60199,60233,60268,60303,60338,60373,60407,60442,60477, + 60511,60546,60581,60615,60650,60684,60719,60753,60788,60822,60857,60891,60926,60960, + 60995,61029,61063,61098,61132,61166,61201,61235,61269,61303,61338,61372,61406,61440, + 61474,61508,61542,61576,61610,61644,61678,61712,61746,61780,61814,61848,61882,61916, + 61950,61984,62018,62051,62085,62119,62153,62186,62220,62254,62287,62321,62355,62388, + 62422,62456,62489,62523,62556,62590,62623,62657,62690,62724,62757,62790,62824,62857, + 62891,62924,62957,62991,63024,63057,63090,63124,63157,63190,63223,63256,63289,63323, + 63356,63389,63422,63455,63488,63521,63554,63587,63620,63653,63686,63719,63752,63785, + 63817,63850,63883,63916,63949,63982,64014,64047,64080,64113,64145,64178,64211,64243, + 64276,64309,64341,64374,64406,64439,64471,64504,64536,64569,64601,64634,64666,64699, + 64731,64763,64796,64828,64861,64893,64925,64957,64990,65022,65054,65086,65119,65151, + 65183,65215,65247,65279,65312,65344,65376,65408,65440,65472,65504 +}; + + +int8 g_elder_bit_table[256] = //---------g_elder_bit_table +{ + 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4, + 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 +}; + +unsigned fast_sqrt(unsigned val) +{ + unsigned t = val; + int bit=0; + unsigned shift = 11; + + bit = t >> 24; + if(bit) + { + bit = g_elder_bit_table[bit] + 24; + } + else + { + bit = (t >> 16) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 16; + } + else + { + bit = (t >> 8) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 8; + } + else + { + bit = g_elder_bit_table[t]; + } + } + } + + //This code calculates the sqrt. + bit -= 9; + if(bit > 0) + { + bit = (bit >> 1) + (bit & 1); + shift -= bit; + val >>= (bit << 1); + } + return g_sqrt_table[val] >> shift; +} + +unsigned fast_sqrt2(unsigned val) +{ + unsigned long bit=0; + unsigned shift = 11; + + _BitScanReverse(&bit, val); +/* if(bit) + { + bit = g_elder_bit_table[bit] + 24; + } + else + { + bit = (t >> 16) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 16; + } + else + { + bit = (t >> 8) & 0xFF; + if(bit) + { + bit = g_elder_bit_table[bit] + 8; + } + else + { + bit = g_elder_bit_table[t]; + } + } + } +*/ + //This code calculates the sqrt. + bit -= 9; + if(bit > 0) + { + bit = (bit >> 1) + (bit & 1); + shift -= bit; + val >>= (bit << 1); + } + return g_sqrt_table[val] >> shift; +} + +CONSOLE_APP_MAIN +{ + int x = 0; + double dx = 0; + for(int i = 0; i < 100; i++) { + { + RTIMING("Fast2"); + for(int i = 0; i < 100000; i++) + x += fast_sqrt2(i); + } + { + RTIMING("Fast"); + for(int i = 0; i < 100000; i++) + x += fast_sqrt(i); + } + { + RTIMING("Normal"); + for(double i = 0; i < 100000.0; i++) + dx += sqrt(i); + } + } + RDUMP(x); + RDUMP(dx); + return; + unsigned long mask = 0x1000; + unsigned long index; + unsigned char isNonzero; + + for(;;) { + Cout() << "Enter a positive integer as the mask: " << '\n'; + mask = atoi(ReadStdIn()); + isNonzero = _BitScanForward(&index, mask); + if (isNonzero) + Cout() << "Mask: " << mask << " Index: " << index << '\n'; + else + Cout() << "No set bits found. Mask is zero."; + } +} diff --git a/uppdev/bsr/bsr.upp b/uppdev/bsr/bsr.upp new file mode 100644 index 000000000..1d99d8e8d --- /dev/null +++ b/uppdev/bsr/bsr.upp @@ -0,0 +1,9 @@ +uses + Core; + +file + bsr.cpp; + +mainconfig + "" = ""; +