void cmsXYZ2LabEncoded(WORD XYZ[3], WORD Lab[3])
{
       Fixed32 X, Y, Z;
       double x, y, z, L, a, b;
       double fx, fy, fz;
       Fixed32 wL, wa, wb;

       X = (Fixed32) XYZ[0] << 1;
       Y = (Fixed32) XYZ[1] << 1;
       Z = (Fixed32) XYZ[2] << 1;


       if (X==0 && Y==0 && Z==0) {

                     Lab[0] = 0;
                     Lab[1] = Lab[2] =  0x8000;
                     return;
       }

       // PCS is in D50


       x = FIXED_TO_DOUBLE(X) / D50X;
       y = FIXED_TO_DOUBLE(Y) / D50Y;
       z = FIXED_TO_DOUBLE(Z) / D50Z;


       fx = f(x);
       fy = f(y);
       fz = f(z);

       L = 116.* fy - 16.;

       a = 500.*(fx - fy);
       b = 200.*(fy - fz);

       a += 128.;
       b += 128.;

       wL = (int) (L * 652.800 + .5);
       wa = (int) (a * 256.0   + .5);
       wb = (int) (b * 256.0   + .5);


       Lab[0] = Clamp_L(wL);
       Lab[1] = Clamp_ab(wa);
       Lab[2] = Clamp_ab(wb);


}
double IOHIDParametricAcceleration::GetCurveParameter (CFDictionaryRef curve, CFStringRef key) {
  CFDictionaryRefWrap curveWrap (curve);
  CFNumberRefWrap value = (CFNumberRef)curveWrap[key];
  if (value.Reference() == NULL) {
    return 0;
  }
  return FIXED_TO_DOUBLE((SInt64)value);
}
static
double XYZ2float(WORD v)
{
       Fixed32 fix32;

       // From 1.15 to 15.16

       fix32 = v << 1;

       // From fixed 15.16 to double

       return FIXED_TO_DOUBLE(fix32);
}
Esempio n. 4
0
idStr& idStr::operator+=
	(
	const gfixed a
	)

	{
   char text[ 20 ];

   sprintf( text, "%f", FIXED_TO_DOUBLE(a) );
	append( text );

   return *this;
	}
Esempio n. 5
0
idStr operator+
   (
   const idStr& a,
   const gfixed b
   )

   {
   char text[ 20 ];

	idStr result( a );

   sprintf( text, "%f", FIXED_TO_DOUBLE(b) );
	result.append( text );

	return result;
   }
Esempio n. 6
0
void R_InitSkyTexCoords( bfixed heightCloud )
{
	int i, s, t;
	bfixed radiusWorld = BFIXED(4096,0);
	double fradiusWorld = 4096.0;
	double fheightCloud = FIXED_TO_DOUBLE(heightCloud);
	float p;
	gfixed sRad, tRad;
	bvec3_t skyVec;
	bvec3_t v;
	float fskyvec[3];
				
	// init zfar so MakeSkyVec works even though
	// a world hasn't been bounded
	backEnd.viewParms.zFar = BFIXED(1024,0);

	for ( i = 0; i < 6; i++ )
	{
		for ( t = 0; t <= SKY_SUBDIVISIONS; t++ )
		{
			for ( s = 0; s <= SKY_SUBDIVISIONS; s++ )
			{
				// compute vector from view origin to sky side integral point
				MakeSkyVec( FIXED_INT32RATIO_G( s - HALF_SKY_SUBDIVISIONS, HALF_SKY_SUBDIVISIONS), 
							FIXED_INT32RATIO_G( t - HALF_SKY_SUBDIVISIONS, HALF_SKY_SUBDIVISIONS), 
							i, 
							NULL,
							skyVec );

				fskyvec[0]=FIXED_TO_FLOAT(skyVec[0]);
				fskyvec[1]=FIXED_TO_FLOAT(skyVec[1]);
				fskyvec[2]=FIXED_TO_FLOAT(skyVec[2]);

				// compute parametric value 'p' that intersects with cloud layer
				p = ( 1.0 / ( 2.0*
					( fskyvec[0]*fskyvec[0] + fskyvec[1]*fskyvec[1] + fskyvec[2]*fskyvec[2] ) 
					) ) *
					( -2.0* fskyvec[2] * fradiusWorld + 
					   2.0* sqrt( SQR( fskyvec[2] ) * SQR( fradiusWorld ) + 
					                             2.0* SQR( fskyvec[0] ) * fradiusWorld * fheightCloud +
								                 SQR( fskyvec[0] ) * SQR( fheightCloud ) + 
								                 2.0* SQR( fskyvec[1] ) * fradiusWorld * fheightCloud +
								                 SQR( fskyvec[1] ) * SQR( fheightCloud ) + 
								                 2.0* SQR( fskyvec[2] ) * fradiusWorld * fheightCloud +
								                 SQR( fskyvec[2] ) * SQR( fheightCloud ) ) );

				s_cloudTexP[i][t][s] = MAKE_GFIXED(p);

				// compute intersection point based on p
				FIXED_VEC3SCALE( skyVec, MAKE_BFIXED(p), v );
				v[2] += radiusWorld;

				// compute vector from world origin to intersection point 'v'
				VectorNormalize( v );

				sRad = MAKE_GFIXED(Q_acos( v[0] ));
				tRad = MAKE_GFIXED(Q_acos( v[1] ));

				s_cloudTexCoords[i][t][s][0] = sRad;
				s_cloudTexCoords[i][t][s][1] = tRad;
			}
		}
	}
}
double ACCEL_TABLE::scale () const {
  return FIXED_TO_DOUBLE(scale<IOFixed>());
}
double ACCEL_TABLE_ENTRY::y (unsigned int index) const {
  return FIXED_TO_DOUBLE(y<IOFixed>(index));
}
double ACCEL_TABLE_ENTRY::acceleration<double> () const {
  return FIXED_TO_DOUBLE(acceleration<IOFixed>());
}
Esempio n. 10
0
// paint the window
void SceneXrender::Window::performPaint(int mask, QRegion region, WindowPaintData data)
{
    setTransformedShape(QRegion());  // maybe nothing will be painted
    // check if there is something to paint
    bool opaque = isOpaque() && qFuzzyCompare(data.opacity(), 1.0);
    /* HACK: It seems this causes painting glitches, disable temporarily
    if (( mask & PAINT_WINDOW_OPAQUE ) ^ ( mask & PAINT_WINDOW_TRANSLUCENT ))
        { // We are only painting either opaque OR translucent windows, not both
        if ( mask & PAINT_WINDOW_OPAQUE && !opaque )
            return; // Only painting opaque and window is translucent
        if ( mask & PAINT_WINDOW_TRANSLUCENT && opaque )
            return; // Only painting translucent and window is opaque
        }*/
    // Intersect the clip region with the rectangle the window occupies on the screen
    if (!(mask & (PAINT_WINDOW_TRANSFORMED | PAINT_SCREEN_TRANSFORMED)))
        region &= toplevel->visibleRect();

    if (region.isEmpty())
        return;
    XRenderWindowPixmap *pixmap = windowPixmap<XRenderWindowPixmap>();
    if (!pixmap || !pixmap->isValid()) {
        return;
    }
    xcb_render_picture_t pic = pixmap->picture();
    if (pic == XCB_RENDER_PICTURE_NONE)   // The render format can be null for GL and/or Xv visuals
        return;
    toplevel->resetDamage();
    // set picture filter
    if (options->isXrenderSmoothScale()) { // only when forced, it's slow
        if (mask & PAINT_WINDOW_TRANSFORMED)
            filter = ImageFilterGood;
        else if (mask & PAINT_SCREEN_TRANSFORMED)
            filter = ImageFilterGood;
        else
            filter = ImageFilterFast;
    } else
        filter = ImageFilterFast;
    // do required transformations
    const QRect wr = mapToScreen(mask, data, QRect(0, 0, width(), height()));
    QRect cr = QRect(toplevel->clientPos(), toplevel->clientSize()); // Client rect (in the window)
    qreal xscale = 1;
    qreal yscale = 1;
    bool scaled = false;

    Client *client = dynamic_cast<Client*>(toplevel);
    Deleted *deleted = dynamic_cast<Deleted*>(toplevel);
    const QRect decorationRect = toplevel->decorationRect();
    if (((client && !client->noBorder()) || (deleted && !deleted->noBorder())) &&
                                                        true) {
        // decorated client
        transformed_shape = decorationRect;
        if (toplevel->shape()) {
            // "xeyes" + decoration
            transformed_shape -= cr;
            transformed_shape += shape();
        }
    } else {
        transformed_shape = shape();
    }
    if (toplevel->hasShadow())
        transformed_shape |= toplevel->shadow()->shadowRegion();

    xcb_render_transform_t xform = {
        DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0),
        DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0),
        DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1)
    };
    static const xcb_render_transform_t identity = {
        DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0),
        DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1), DOUBLE_TO_FIXED(0),
        DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1)
    };

    if (mask & PAINT_WINDOW_TRANSFORMED) {
        xscale = data.xScale();
        yscale = data.yScale();
    }
    if (mask & PAINT_SCREEN_TRANSFORMED) {
        xscale *= screen_paint.xScale();
        yscale *= screen_paint.yScale();
    }
    if (!qFuzzyCompare(xscale, 1.0) || !qFuzzyCompare(yscale, 1.0)) {
        scaled = true;
        xform.matrix11 = DOUBLE_TO_FIXED(1.0 / xscale);
        xform.matrix22 = DOUBLE_TO_FIXED(1.0 / yscale);

        // transform the shape for clipping in paintTransformedScreen()
        QVector<QRect> rects = transformed_shape.rects();
        for (int i = 0; i < rects.count(); ++i) {
            QRect& r = rects[ i ];
            r.setRect(qRound(r.x() * xscale), qRound(r.y() * yscale),
                      qRound(r.width() * xscale), qRound(r.height() * yscale));
        }
        transformed_shape.setRects(rects.constData(), rects.count());
    }

    transformed_shape.translate(mapToScreen(mask, data, QPoint(0, 0)));
    PaintClipper pcreg(region);   // clip by the region to paint
    PaintClipper pc(transformed_shape);   // clip by window's shape

    const bool wantShadow = m_shadow && !m_shadow->shadowRegion().isEmpty();

    // In order to obtain a pixel perfect rescaling
    // we need to blit the window content togheter with
    // decorations in a temporary pixmap and scale
    // the temporary pixmap at the end.
    // We should do this only if there is scaling and
    // the window has border
    // This solves a number of glitches and on top of this
    // it optimizes painting quite a bit
    const bool blitInTempPixmap = xRenderOffscreen() || (data.crossFadeProgress() < 1.0 && !opaque) ||
                                 (scaled && (wantShadow || (client && !client->noBorder()) || (deleted && !deleted->noBorder())));

    xcb_render_picture_t renderTarget = m_scene->bufferPicture();
    if (blitInTempPixmap) {
        if (scene_xRenderOffscreenTarget()) {
            temp_visibleRect = toplevel->visibleRect().translated(-toplevel->pos());
            renderTarget = *scene_xRenderOffscreenTarget();
        } else {
            prepareTempPixmap();
            renderTarget = *s_tempPicture;
        }
    } else {
        xcb_render_set_picture_transform(connection(), pic, xform);
        if (filter == ImageFilterGood) {
            setPictureFilter(pic, KWin::Scene::ImageFilterGood);
        }

        //BEGIN OF STUPID RADEON HACK
        // This is needed to avoid hitting a fallback in the radeon driver.
        // The Render specification states that sampling pixels outside the
        // source picture results in alpha=0 pixels. This can be achieved by
        // setting the border color to transparent black, but since the border
        // color has the same format as the texture, it only works when the
        // texture has an alpha channel. So the driver falls back to software
        // when the repeat mode is RepeatNone, the picture has a non-identity
        // transformation matrix, and doesn't have an alpha channel.
        // Since we only scale the picture, we can work around this by setting
        // the repeat mode to RepeatPad.
        if (!window()->hasAlpha()) {
            const uint32_t values[] = {XCB_RENDER_REPEAT_PAD};
            xcb_render_change_picture(connection(), pic, XCB_RENDER_CP_REPEAT, values);
        }
        //END OF STUPID RADEON HACK
    }
#define MAP_RECT_TO_TARGET(_RECT_) \
        if (blitInTempPixmap) _RECT_.translate(-temp_visibleRect.topLeft()); else _RECT_ = mapToScreen(mask, data, _RECT_)

    //BEGIN deco preparations
    bool noBorder = true;
    xcb_render_picture_t left   = XCB_RENDER_PICTURE_NONE;
    xcb_render_picture_t top    = XCB_RENDER_PICTURE_NONE;
    xcb_render_picture_t right  = XCB_RENDER_PICTURE_NONE;
    xcb_render_picture_t bottom = XCB_RENDER_PICTURE_NONE;
    QRect dtr, dlr, drr, dbr;
    const SceneXRenderDecorationRenderer *renderer = nullptr;
    if (client) {
        if (client && !client->noBorder()) {
            if (client->isDecorated()) {
                SceneXRenderDecorationRenderer *r = static_cast<SceneXRenderDecorationRenderer*>(client->decoratedClient()->renderer());
                if (r) {
                    r->render();
                    renderer = r;
                }
            }
            noBorder = client->noBorder();
            client->layoutDecorationRects(dlr, dtr, drr, dbr);
        }
    }
    if (deleted && !deleted->noBorder()) {
        renderer = static_cast<const SceneXRenderDecorationRenderer*>(deleted->decorationRenderer());
        noBorder = deleted->noBorder();
        deleted->layoutDecorationRects(dlr, dtr, drr, dbr);
    }
    if (renderer) {
        left   = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Left);
        top    = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Top);
        right  = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Right);
        bottom = renderer->picture(SceneXRenderDecorationRenderer::DecorationPart::Bottom);
    }
    if (!noBorder) {
        MAP_RECT_TO_TARGET(dtr);
        MAP_RECT_TO_TARGET(dlr);
        MAP_RECT_TO_TARGET(drr);
        MAP_RECT_TO_TARGET(dbr);
    }
    //END deco preparations

    //BEGIN shadow preparations
    QRect stlr, str, strr, srr, sbrr, sbr, sblr, slr;
    SceneXRenderShadow* m_xrenderShadow = static_cast<SceneXRenderShadow*>(m_shadow);

    if (wantShadow) {
        m_xrenderShadow->layoutShadowRects(str, strr, srr, sbrr, sbr, sblr, slr, stlr);
        MAP_RECT_TO_TARGET(stlr);
        MAP_RECT_TO_TARGET(str);
        MAP_RECT_TO_TARGET(strr);
        MAP_RECT_TO_TARGET(srr);
        MAP_RECT_TO_TARGET(sbrr);
        MAP_RECT_TO_TARGET(sbr);
        MAP_RECT_TO_TARGET(sblr);
        MAP_RECT_TO_TARGET(slr);
    }
    //BEGIN end preparations

    //BEGIN client preparations
    QRect dr = cr;
    if (blitInTempPixmap) {
        dr.translate(-temp_visibleRect.topLeft());
    } else {
        dr = mapToScreen(mask, data, dr); // Destination rect
        if (scaled) {
            cr.moveLeft(cr.x() * xscale);
            cr.moveTop(cr.y() * yscale);
        }
    }

    const int clientRenderOp = (opaque || blitInTempPixmap) ? XCB_RENDER_PICT_OP_SRC : XCB_RENDER_PICT_OP_OVER;
    //END client preparations

#undef MAP_RECT_TO_TARGET

    for (PaintClipper::Iterator iterator; !iterator.isDone(); iterator.next()) {

#define RENDER_SHADOW_TILE(_TILE_, _RECT_) \
xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, m_xrenderShadow->picture(SceneXRenderShadow::ShadowElement##_TILE_), \
                 shadowAlpha, renderTarget, 0, 0, 0, 0, _RECT_.x(), _RECT_.y(), _RECT_.width(), _RECT_.height())

        //shadow
        if (wantShadow) {
            xcb_render_picture_t shadowAlpha = XCB_RENDER_PICTURE_NONE;
            if (!opaque) {
                shadowAlpha = xRenderBlendPicture(data.opacity());
            }
            RENDER_SHADOW_TILE(TopLeft, stlr);
            RENDER_SHADOW_TILE(Top, str);
            RENDER_SHADOW_TILE(TopRight, strr);
            RENDER_SHADOW_TILE(Left, slr);
            RENDER_SHADOW_TILE(Right, srr);
            RENDER_SHADOW_TILE(BottomLeft, sblr);
            RENDER_SHADOW_TILE(Bottom, sbr);
            RENDER_SHADOW_TILE(BottomRight, sbrr);
        }
#undef RENDER_SHADOW_TILE

        // Paint the window contents
        if (!(client && client->isShade())) {
            xcb_render_picture_t clientAlpha = XCB_RENDER_PICTURE_NONE;
            if (!opaque) {
                clientAlpha = xRenderBlendPicture(data.opacity());
            }
            xcb_render_composite(connection(), clientRenderOp, pic, clientAlpha, renderTarget,
                                 cr.x(), cr.y(), 0, 0, dr.x(), dr.y(), dr.width(), dr.height());
            if (data.crossFadeProgress() < 1.0 && data.crossFadeProgress() > 0.0) {
                XRenderWindowPixmap *previous = previousWindowPixmap<XRenderWindowPixmap>();
                if (previous && previous != pixmap) {
                    static XRenderPicture cFadeAlpha(XCB_RENDER_PICTURE_NONE);
                    static xcb_render_color_t cFadeColor = {0, 0, 0, 0};
                    cFadeColor.alpha = uint16_t((1.0 - data.crossFadeProgress()) * 0xffff);
                    if (cFadeAlpha == XCB_RENDER_PICTURE_NONE) {
                        cFadeAlpha = xRenderFill(cFadeColor);
                    } else {
                        xcb_rectangle_t rect = {0, 0, 1, 1};
                        xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_SRC, cFadeAlpha, cFadeColor , 1, &rect);
                    }
                    if (previous->size() != pixmap->size()) {
                        xcb_render_transform_t xform2 = {
                            DOUBLE_TO_FIXED(FIXED_TO_DOUBLE(xform.matrix11) * previous->size().width() / pixmap->size().width()), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0),
                            DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(FIXED_TO_DOUBLE(xform.matrix22) * previous->size().height() / pixmap->size().height()), DOUBLE_TO_FIXED(0),
                            DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(0), DOUBLE_TO_FIXED(1)
                            };
                        xcb_render_set_picture_transform(connection(), previous->picture(), xform2);
                    }

                    xcb_render_composite(connection(), opaque ? XCB_RENDER_PICT_OP_OVER : XCB_RENDER_PICT_OP_ATOP,
                                         previous->picture(), cFadeAlpha, renderTarget,
                                         cr.x(), cr.y(), 0, 0, dr.x(), dr.y(), dr.width(), dr.height());

                    if (previous->size() != pixmap->size()) {
                        xcb_render_set_picture_transform(connection(), previous->picture(), identity);
                    }
                }
            }
            if (!opaque)
                transformed_shape = QRegion();
        }

        if (client || deleted) {
            if (!noBorder) {
                xcb_render_picture_t decorationAlpha = xRenderBlendPicture(data.opacity());
                auto renderDeco = [decorationAlpha, renderTarget](xcb_render_picture_t deco, const QRect &rect) {
                    if (deco == XCB_RENDER_PICTURE_NONE) {
                        return;
                    }
                    xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, deco, decorationAlpha, renderTarget,
                                         0, 0, 0, 0, rect.x(), rect.y(), rect.width(), rect.height());
                };
                renderDeco(top, dtr);
                renderDeco(left, dlr);
                renderDeco(right, drr);
                renderDeco(bottom, dbr);
            }
        }

        if (data.brightness() != 1.0) {
            // fake brightness change by overlaying black
            const float alpha = (1 - data.brightness()) * data.opacity();
            xcb_rectangle_t rect;
            if (blitInTempPixmap) {
                rect.x = -temp_visibleRect.left();
                rect.y = -temp_visibleRect.top();
                rect.width = width();
                rect.height = height();
            } else {
                rect.x = wr.x();
                rect.y = wr.y();
                rect.width = wr.width();
                rect.height = wr.height();
            }
            xcb_render_fill_rectangles(connection(), XCB_RENDER_PICT_OP_OVER, renderTarget,
                                       preMultiply(data.brightness() < 1.0 ? QColor(0,0,0,255*alpha) : QColor(255,255,255,-alpha*255)),
                                       1, &rect);
        }
        if (blitInTempPixmap) {
            const QRect r = mapToScreen(mask, data, temp_visibleRect);
            xcb_render_set_picture_transform(connection(), *s_tempPicture, xform);
            setPictureFilter(*s_tempPicture, filter);
            xcb_render_composite(connection(), XCB_RENDER_PICT_OP_OVER, *s_tempPicture,
                                 XCB_RENDER_PICTURE_NONE, m_scene->bufferPicture(),
                                 0, 0, 0, 0, r.x(), r.y(), r.width(), r.height());
            xcb_render_set_picture_transform(connection(), *s_tempPicture, identity);
        }
    }
    if (scaled && !blitInTempPixmap) {
        xcb_render_set_picture_transform(connection(), pic, identity);
        if (filter == ImageFilterGood)
            setPictureFilter(pic, KWin::Scene::ImageFilterFast);
        if (!window()->hasAlpha()) {
            const uint32_t values[] = {XCB_RENDER_REPEAT_NONE};
            xcb_render_change_picture(connection(), pic, XCB_RENDER_CP_REPEAT, values);
        }
    }
    if (xRenderOffscreen())
        scene_setXRenderOffscreenTarget(*s_tempPicture);
}
IOHIDTableAcceleration * IOHIDTableAcceleration::CreateOriginalWithTable (CFDataRef table, double acceleration, const double resolution, const double rate)
{

    double	scale;
    UInt32	count;
    Boolean	isLower;

    ACCEL_POINT lower, upper, p1, p2, p3, prev, curveP1, curveP2;
    double      loAccel, hiAccel;
    const void *  loTable = NULL;
    const void *  hiTable = NULL;
    unsigned int loCount, hiCount;
    p1 = prev = curveP1 = curveP2 = {0,0};
    loCount = hiCount = 0;
    loAccel = 0;

    if( table == NULL || resolution == 0 || rate == 0) {
        return NULL;
    }

    IOHIDTableAcceleration * self = new IOHIDTableAcceleration;

    if (self == NULL) {
        return NULL;
    }
    self->resolution_ = resolution;
    self->rate_ = rate;

    hiTable = CFDataGetBytePtr(table);

    scale = FIXED_TO_DOUBLE(ACCEL_TABLE_CONSUME_INT32(&hiTable));
    ACCEL_TABLE_CONSUME_INT32(&hiTable);
    // normalize table's default (scale) to 0.5
    if( acceleration > 0.5) {
        acceleration =  (acceleration - 0.5) * (1 - scale ) * 2 + scale ;
    } else {
        acceleration = acceleration * scale ;
    }

    count = ACCEL_TABLE_CONSUME_INT16(&hiTable);
    scale = 1.0;

    // find curves bracketing the desired value
    do {
        hiAccel =  FIXED_TO_DOUBLE(ACCEL_TABLE_CONSUME_INT32(&hiTable));
        hiCount =  ACCEL_TABLE_CONSUME_INT16 (&hiTable);

        if( acceleration <= hiAccel) {
            break;
        }

        if( 0 == --count) {
            // this much over the highest table
            scale = (hiAccel) ? (acceleration / hiAccel ) : 0;
            loTable = NULL;
            break;
        }

        loTable    = hiTable;
        loAccel	   = hiAccel;
        loCount    = hiCount;
        hiTable    = (uint8_t*)hiTable + loCount * 8;

    } while (true);

    // scale between the two
    if( loTable) {
        scale = (hiAccel == loAccel) ? 0 : (acceleration - loAccel) / (hiAccel - loAccel);
    }
    // or take all the high one
    else {
        loTable  = hiTable;
        //loAccel	 = hiAccel;
        loCount  = 0;
    }

    lower = ACCELL_TABLE_CONSUME_POINT(&loTable);
    upper = ACCELL_TABLE_CONSUME_POINT(&hiTable);

    do {
        // consume next point from first X
        isLower = (loCount && (!hiCount || (lower.x <= upper.x)));

        if( isLower) {
            /* highline */
            p2 = upper;
            p3 = lower;
            if( loCount && (--loCount)) {
                lower = ACCELL_TABLE_CONSUME_POINT(&loTable);
            }
        } else  {
            /* lowline */
            p2 = lower;
            p3 = upper;
            if( hiCount && (--hiCount)) {
                upper  = ACCELL_TABLE_CONSUME_POINT(&hiTable);
            }
        }
        {

            curveP2 = InterpolatePoint(p3, p1, p2 , scale, isLower);
            curveP2.x *= (resolution/rate);
            curveP2.y *= kCursorScale;

            ACCEL_SEGMENT segment;

            segment.m = (curveP2.x == curveP1.x) ? 0 : (curveP2.y - curveP1.y) / (curveP2.x - curveP1.x),
                    segment.b = curveP2.y - segment.m * curveP2.x,
                            segment.x = (loCount || hiCount) ? curveP2.x : MAX_DEVICE_THRESHOLD;

            self->segments_.push_back ({
                segment
            });

            curveP1 = curveP2;
        }

        // continue on from last point
        if( loCount && hiCount) {
            if( lower.x > upper.x) {
                prev = p1;
            } else {
                prev = p1;
                p1 = p3;
            }
        } else {
            p2 = p1;
            p1 = prev;
            prev = p2;
        }

    } while( loCount || hiCount );

    return self;
}