📄 qdrawhelper.cpp
字号:
+ data->m12 * (x + 0.5) + data->dy) * fixed_scale); const uint *end = buffer + length; uint *b = buffer; while (b < end) { int x1 = (fx >> 16); int x2 = x1 + 1; int y1 = (fy >> 16); int y2 = y1 + 1; int distx = ((fx - (x1 << 16)) >> 8); int disty = ((fy - (y1 << 16)) >> 8); int idistx = 256 - distx; int idisty = 256 - disty; bool x1_out = ((x1 < 0) || (x1 >= image_width)); bool x2_out = ((x2 < 0) || (x2 >= image_width)); bool y1_out = ((y1 < 0) || (y1 >= image_height)); bool y2_out = ((y2 < 0) || (y2 >= image_height)); const uchar *s1 = data->texture.scanLine(y1); const uchar *s2 = s1 + data->texture.bytesPerLine; uint tl = (x1_out || y1_out) ? uint(0) : fetch(s1, x1, data->texture.colorTable); uint tr = (x2_out || y1_out) ? uint(0) : fetch(s1, x2, data->texture.colorTable); uint bl = (x1_out || y2_out) ? uint(0) : fetch(s2, x1, data->texture.colorTable); uint br = (x2_out || y2_out) ? uint(0) : fetch(s2, x2, data->texture.colorTable); uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); fx += fdx; fy += fdy; ++b; } return buffer;}static const uint * QT_FASTCALL fetchTransformedBilinearTiled_generic(uint *buffer, const Operator *, const QSpanData *data, int y, int x, int length){ FetchPixelProc fetch = fetchPixelProc[data->texture.format]; int image_width = data->texture.width; int image_height = data->texture.height; // The increment pr x in the scanline int fdx = (int)(data->m11 * fixed_scale); int fdy = (int)(data->m12 * fixed_scale); int fx = int((data->m21 * (y + 0.5) + data->m11 * (x + 0.5) + data->dx) * fixed_scale); int fy = int((data->m22 * (y + 0.5) + data->m12 * (x + 0.5) + data->dy) * fixed_scale); const uint *end = buffer + length; uint *b = buffer; while (b < end) { int x1 = (fx >> 16); int x2 = x1 + 1; int y1 = (fy >> 16); int y2 = y1 + 1; int distx = ((fx - (x1 << 16)) >> 8); int disty = ((fy - (y1 << 16)) >> 8); int idistx = 256 - distx; int idisty = 256 - disty; x1 %= image_width; x2 %= image_width; y1 %= image_height; y2 %= image_height; if (x1 < 0) x1 += image_width; if (x2 < 0) x2 += image_width; if (y1 < 0) y1 += image_height; if (y2 < 0) y2 += image_height; Q_ASSERT(x1 >= 0 && x1 < image_width); Q_ASSERT(x2 >= 0 && x2 < image_width); Q_ASSERT(y1 >= 0 && y1 < image_height); Q_ASSERT(y2 >= 0 && y2 < image_height); const uchar *s1 = data->texture.scanLine(y1); const uchar *s2 = data->texture.scanLine(y2); uint tl = fetch(s1, x1, data->texture.colorTable); uint tr = fetch(s1, x2, data->texture.colorTable); uint bl = fetch(s2, x1, data->texture.colorTable); uint br = fetch(s2, x2, data->texture.colorTable); uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx); uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx); *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty); fx += fdx; fy += fdy; ++b; } return buffer;}static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = { // Untransformed { 0, // Invalid fetch_generic, // Mono fetch_generic, // MonoLsb fetch_generic, // Indexed8 fetch_generic, // RGB32 fetch_generic, // ARGB32 fetch_generic#ifdef Q_WS_QWS , fetch_generic#endif }, // ARGB32_Premultiplied // Tiled { 0, // Invalid fetch_generic, // Mono fetch_generic, // MonoLsb fetch_generic, // Indexed8 fetch_generic, // RGB32 fetch_generic, // ARGB32 fetch_generic#ifdef Q_WS_QWS , fetch_generic#endif }, // ARGB32_Premultiplied // Transformed { 0, // Invalid fetchTransformed_generic, // Mono fetchTransformed_generic, // MonoLsb fetchTransformed_generic, // Indexed8 fetchTransformed_generic, // RGB32 fetchTransformed_generic, // ARGB32 fetchTransformed_generic#ifdef Q_WS_QWS , fetchTransformed_generic#endif }, // ARGB32_Premultiplied { 0, // TransformedTiled fetchTransformedTiled_generic, // Mono fetchTransformedTiled_generic, // MonoLsb fetchTransformedTiled_generic, // Indexed8 fetchTransformedTiled_generic, // RGB32 fetchTransformedTiled_generic, // ARGB32 fetchTransformedTiled_generic#ifdef Q_WS_QWS , fetchTransformedTiled_generic#endif }, // ARGB32_Premultiplied { 0, // Bilinear fetchTransformedBilinear_generic, // Mono fetchTransformedBilinear_generic, // MonoLsb fetchTransformedBilinear_generic, // Indexed8 fetchTransformedBilinear_generic, // RGB32 fetchTransformedBilinear_generic, // ARGB32 fetchTransformedBilinear_generic#ifdef Q_WS_QWS , fetchTransformedBilinear_generic#endif }, // ARGB32_Premultiplied { 0, // BilinearTiled fetchTransformedBilinearTiled_generic, // Mono fetchTransformedBilinearTiled_generic, // MonoLsb fetchTransformedBilinearTiled_generic, // Indexed8 fetchTransformedBilinearTiled_generic, // RGB32 fetchTransformedBilinearTiled_generic, // ARGB32 fetchTransformedBilinearTiled_generic#ifdef Q_WS_QWS , fetchTransformedBilinearTiled_generic#endif }, // ARGB32_Premultiplied};static uint qt_gradient_pixel(const GradientData *data, qreal pos){ int ipos = qRound(pos * GRADIENT_STOPTABLE_SIZE - 1); // calculate the actual offset. if (ipos < 0 || ipos >= GRADIENT_STOPTABLE_SIZE) { if (data->spread == QGradient::RepeatSpread) { ipos = ipos % GRADIENT_STOPTABLE_SIZE; ipos = ipos < 0 ? GRADIENT_STOPTABLE_SIZE + ipos : ipos; } else if (data->spread == QGradient::ReflectSpread) { const int limit = GRADIENT_STOPTABLE_SIZE * 2 - 1; ipos = ipos % limit; ipos = ipos < 0 ? limit + ipos : ipos; ipos = ipos >= GRADIENT_STOPTABLE_SIZE ? limit - ipos : ipos; } else { if (ipos < 0) ipos = 0; else if (ipos >= GRADIENT_STOPTABLE_SIZE) ipos = GRADIENT_STOPTABLE_SIZE-1; } } Q_ASSERT(ipos >= 0); Q_ASSERT(ipos < GRADIENT_STOPTABLE_SIZE); return data->colorTable[ipos];}static void QT_FASTCALL getLinearGradientValues(LinearGradientValues *v, const QSpanData *data){ v->dx = data->gradient.linear.end.x - data->gradient.linear.origin.x; v->dy = data->gradient.linear.end.y - data->gradient.linear.origin.y; v->l = v->dx * v->dx + v->dy * v->dy; v->off = 0; if (v->l != 0) { v->dx /= v->l; v->dy /= v->l; v->off = -v->dx * data->gradient.linear.origin.x - v->dy * data->gradient.linear.origin.y; }}static const uint * QT_FASTCALL fetchLinearGradient(uint *buffer, const Operator *op, const QSpanData *data, int y, int x, int length){ const uint *b = buffer; qreal t, inc; if (op->linear.l == 0) { t = inc = 0; } else { qreal rx = data->m21 * y + data->m11 * x + data->dx; qreal ry = data->m22 * y + data->m12 * x + data->dy; t = op->linear.dx*rx + op->linear.dy*ry + op->linear.off; inc = op->linear.dx * data->m11 + op->linear.dy * data->m12; } const uint *end = buffer + length; while (buffer < end) { *buffer = qt_gradient_pixel(&data->gradient, t); t += inc; ++buffer; } return b;}static inline qreal determinant(qreal a, qreal b, qreal c){ return (b * b) - (4 * a * c);}// function to evaluate real rootsstatic inline qreal realRoots(qreal a, qreal b, qreal detSqrt){ return (-b + detSqrt)/(2 * a);}static void QT_FASTCALL getRadialGradientValues(RadialGradientValues *v, const QSpanData *data){ v->dx = data->gradient.radial.center.x - data->gradient.radial.focal.x; v->dy = data->gradient.radial.center.y - data->gradient.radial.focal.y; v->a = data->gradient.radial.radius*data->gradient.radial.radius - v->dx*v->dx - v->dy*v->dy;}static const uint * QT_FASTCALL fetchRadialGradient(uint *buffer, const Operator *op, const QSpanData *data, int y, int x, int length){ const uint *b = buffer; qreal rx = data->m21 * (y + 0.5) + data->dx + data->m11 * (x + 0.5) - data->gradient.radial.focal.x; qreal ry = data->m22 * (y + 0.5) + data->dy + data->m12 * (x + 0.5) - data->gradient.radial.focal.y; //qreal r = data->gradient.radial.radius; const uint *end = buffer + length; while (buffer < end) { qreal b = 2*(rx*op->radial.dx + ry*op->radial.dy); qreal det = determinant(op->radial.a, b , -(rx*rx + ry*ry)); qreal s = realRoots(op->radial.a, b, sqrt(det)); *buffer = qt_gradient_pixel(&data->gradient, s); rx += data->m11; ry += data->m12; ++buffer; } return b;}static const uint * QT_FASTCALL fetchConicalGradient(uint *buffer, const Operator *, const QSpanData *data, int y, int x, int length){ const uint *b = buffer; qreal rx = data->m21 * (y + 0.5) + data->dx + data->m11 * (x + 0.5) - data->gradient.conical.center.x; qreal ry = data->m22 * (y + 0.5) + data->dy + data->m12 * (x + 0.5) - data->gradient.conical.center.y; const uint *end = buffer + length; while (buffer < end) { qreal angle = atan2(ry, rx) + data->gradient.conical.angle; *buffer = qt_gradient_pixel(&data->gradient, 1. - angle / (2*Q_PI)); rx += data->m11; ry += data->m12; ++buffer; } return b;}/* The constant alpha factor describes an alpha factor that gets applied to the result of the composition operation combining it with the destination. The intent is that if const_alpha == 0. we get back dest, and if const_alpha == 1. we get the unmodified operation result = src op dest dest = result * const_alpha + dest * (1. - const_alpha) This means that in the comments below, the first line is the const_alpha==255 case, the second line the general one. In the lines below: s == src, sa == alpha(src), sia = 1 - alpha(src) d == dest, da == alpha(dest), dia = 1 - alpha(dest) ca = const_alpha, cia = 1 - const_alpha The methods exist in two variants. One where we have a constant source, the other where the source is an array of pixels.*//* result = 0 d = d * cia*/static void QT_FASTCALL comp_func_solid_Clear(uint *dest, int length, uint, uint const_alpha){ if (const_alpha == 255) { QT_MEMFILL_UINT(dest, length, 0); } else { int ialpha = 255 - const_alpha; for (int i = 0; i < length; ++i) dest[i] = BYTE_MUL(dest[i], ialpha); }}static void QT_FASTCALL comp_func_Clear(uint *dest, const uint *, int length, uint const_alpha){ if (const_alpha == 255) { QT_MEMFILL_UINT(dest, length, 0); } else { int ialpha = 255 - const_alpha; for (int i = 0; i < length; ++i) dest[i] = BYTE_MUL(dest[i], ialpha); }}/* result = s dest = s * ca + d * cia*/static void QT_FASTCALL comp_func_solid_Source(uint *dest, int length, uint color, uint const_alpha){ if (const_alpha == 255) { QT_MEMFILL_UINT(dest, length, color); } else { int ialpha = 255 - const_alpha; color = BYTE_MUL(color, const_alpha); for (int i = 0; i < length; ++i) dest[i] = color + BYTE_MUL(dest[i], ialpha); }}static void QT_FASTCALL comp_func_Source(uint *dest, const uint *src, int length, uint const_alpha){ if (const_alpha == 255) { ::memcpy(dest, src, length * sizeof(uint)); } else { int ialpha = 255 - const_alpha; for (int i = 0; i < length; ++i) dest[i] = INTERPOLATE_PIXEL_255(src[i], const_alpha, dest[i], ialpha); }}/* result = s + d * sia dest = (s + d * sia) * ca + d * cia = s * ca + d * (sia * ca + cia) = s * ca + d * (1 - sa*ca)*/static void QT_FASTCALL comp_func_solid_SourceOver(uint *dest, int length, uint color, uint const_alpha){ if ((const_alpha & qAlpha(color)) == 255) { QT_MEMFILL_UINT(dest, length, color); } else { if (const_alpha != 255) color = BYTE_MUL(color, const_alpha);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -