static inline void assert_color(skiatest::Reporter* reporter, SkColor expected, SkColor actual, int tolerance) { REPORTER_ASSERT(reporter, abs((int)(SkColorGetA(expected) - SkColorGetA(actual))) <= tolerance); REPORTER_ASSERT(reporter, abs((int)(SkColorGetR(expected) - SkColorGetR(actual))) <= tolerance); REPORTER_ASSERT(reporter, abs((int)(SkColorGetG(expected) - SkColorGetG(actual))) <= tolerance); REPORTER_ASSERT(reporter, abs((int)(SkColorGetB(expected) - SkColorGetB(actual))) <= tolerance); }
void setupShapePaint(SkCanvas* canvas, GrColor color, SkXfermode::Mode mode, SkPaint* paint) { paint->setColor(color); if (mode == SkXfermode::kPlus_Mode) { // Check for overflow, otherwise we might get confusing AA artifacts. int maxSum = SkTMax(SkTMax(SkColorGetA(kBGColor) + SkColorGetA(color), SkColorGetR(kBGColor) + SkColorGetR(color)), SkTMax(SkColorGetG(kBGColor) + SkColorGetG(color), SkColorGetB(kBGColor) + SkColorGetB(color))); if (maxSum > 255) { SkPaint dimPaint; dimPaint.setAntiAlias(false); dimPaint.setXfermode(SkXfermode::Create(SkXfermode::kDstIn_Mode)); if (255 != paint->getAlpha()) { // Dim the src and dst colors. dimPaint.setARGB(255 * 255 / maxSum, 0, 0, 0); paint->setAlpha(255 * paint->getAlpha() / maxSum); } else { // Just clear the dst, we need to preserve the paint's opacity. dimPaint.setARGB(0, 0, 0, 0); } canvas->drawRectCoords(-kShapeSpacing/2, -kShapeSpacing/2, kShapeSpacing/2 + 3 * kShapeTypeSpacing, kShapeSpacing/2, dimPaint); } } }
static SkColor GetColor(SkRandom* random, int i, int nextColor) { static SkColor colors[] = { SK_ColorRED, sk_tool_utils::color_to_565(0xFFFF7F00), // Orange SK_ColorYELLOW, SK_ColorGREEN, SK_ColorBLUE, sk_tool_utils::color_to_565(0xFF4B0082), // indigo sk_tool_utils::color_to_565(0xFF7F00FF) }; // violet SkColor color; int index = nextColor % SK_ARRAY_COUNT(colors); switch (i) { case 0: color = SK_ColorTRANSPARENT; break; case 1: color = SkColorSetARGB(0xff, SkColorGetR(colors[index]), SkColorGetG(colors[index]), SkColorGetB(colors[index])); break; default: uint8_t alpha = 0x80; color = SkColorSetARGB(alpha, SkColorGetR(colors[index]), SkColorGetG(colors[index]), SkColorGetB(colors[index])); break; } return color; }
SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) { mul &= 0x00FFFFFF; add &= 0x00FFFFFF; if (0xFFFFFF == mul) { if (0 == add) { return SkNEW(SkSimpleColorFilter); // no change to the colors } else { return SkNEW_ARGS(SkLightingColorFilter_JustAdd, (mul, add)); } } if (0 == add) { if (SkColorGetR(mul) == SkColorGetG(mul) && SkColorGetR(mul) == SkColorGetB(mul)) { return SkNEW_ARGS(SkLightingColorFilter_SingleMul, (mul, add)); } else { return SkNEW_ARGS(SkLightingColorFilter_JustMul, (mul, add)); } } if (SkColorGetR(mul) + SkColorGetR(add) <= 255 && SkColorGetG(mul) + SkColorGetG(add) <= 255 && SkColorGetB(mul) + SkColorGetB(add) <= 255) { return SkNEW_ARGS(SkLightingColorFilter_NoPin, (mul, add)); } return SkNEW_ARGS(SkLightingColorFilter, (mul, add)); }
/** We take the original colors, not our premultiplied PMColors, since we can build a 16bit table as long as the original colors are opaque, even if the paint specifies a non-opaque alpha. */ void SkGradientShaderBase::GradientShaderCache::Build16bitCache( uint16_t cache[], SkColor c0, SkColor c1, int count, bool dither) { SkASSERT(count > 1); SkASSERT(SkColorGetA(c0) == 0xFF); SkASSERT(SkColorGetA(c1) == 0xFF); SkFixed r = SkColorGetR(c0); SkFixed g = SkColorGetG(c0); SkFixed b = SkColorGetB(c0); SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1); r = SkIntToFixed(r) + 0x8000; g = SkIntToFixed(g) + 0x8000; b = SkIntToFixed(b) + 0x8000; if (dither) { do { unsigned rr = r >> 16; unsigned gg = g >> 16; unsigned bb = b >> 16; cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb)); cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb); cache += 1; r += dr; g += dg; b += db; } while (--count != 0); } else { do {
SkLightingColorFilter_SingleMul(SkColor mul, SkColor add) : INHERITED(mul, add) { SkASSERT(SkColorGetR(add) == 0); SkASSERT(SkColorGetG(add) == 0); SkASSERT(SkColorGetB(add) == 0); SkASSERT(SkColorGetR(mul) == SkColorGetG(mul)); SkASSERT(SkColorGetR(mul) == SkColorGetB(mul)); }
void draw_shadow(SkCanvas* canvas, const SkPath& path, SkScalar height, SkColor color, SkPoint3 lightPos, SkScalar lightR, bool isAmbient, uint32_t flags) { SkScalar ambientAlpha = isAmbient ? .5f : 0.f; SkScalar spotAlpha = isAmbient ? 0.f : .5f; SkColor ambientColor = SkColorSetARGB(ambientAlpha*SkColorGetA(color), SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)); SkColor spotColor = SkColorSetARGB(spotAlpha*SkColorGetA(color), SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)); SkShadowUtils::DrawShadow(canvas, path, SkPoint3{ 0, 0, height}, lightPos, lightR, ambientColor, spotColor, flags); }
DEF_TEST(SkColorSpace_New_TransferFnStages, r) { // We'll create a little SkRasterPipelineBlitter-like scenario, // blending the same src color over the same dst color, but with // three different transfer functions, for simplicity the same for src and dst. SkColor src = 0x7f7f0000; SkColor dsts[3]; for (SkColor& dst : dsts) { dst = 0xff007f00; } auto gamut = SkMatrix44::I(); auto blending = SkColorSpace_New::Blending::Linear; SkColorSpace_New linear{SkColorSpace_New::TransferFn::MakeLinear(), gamut, blending}, srgb{SkColorSpace_New::TransferFn::MakeSRGB(), gamut, blending}, gamma{SkColorSpace_New::TransferFn::MakeGamma(3), gamut, blending}; SkColor* dst = dsts; for (const SkColorSpace_New* cs : {&linear, &srgb, &gamma}) { SkJumper_MemoryCtx src_ctx = { &src, 0 }, dst_ctx = { dst++, 0 }; SkRasterPipeline_<256> p; p.append(SkRasterPipeline::load_8888, &src_ctx); cs->transferFn().linearizeSrc(&p); p.append(SkRasterPipeline::premul); p.append(SkRasterPipeline::load_8888_dst, &dst_ctx); cs->transferFn().linearizeDst(&p); p.append(SkRasterPipeline::premul_dst); p.append(SkRasterPipeline::srcover); p.append(SkRasterPipeline::unpremul); cs->transferFn().encodeSrc(&p); p.append(SkRasterPipeline::store_8888, &dst_ctx); p.run(0,0,1,1); } // Double check the uninteresting channels: alpha's opaque, no blue. REPORTER_ASSERT(r, SkColorGetA(dsts[0]) == 0xff && SkColorGetB(dsts[0]) == 0x00); REPORTER_ASSERT(r, SkColorGetA(dsts[1]) == 0xff && SkColorGetB(dsts[1]) == 0x00); REPORTER_ASSERT(r, SkColorGetA(dsts[2]) == 0xff && SkColorGetB(dsts[2]) == 0x00); // Because we're doing linear blending, a more-exponential transfer function will // brighten the encoded values more when linearizing. So we expect to see that // linear is darker than sRGB, and sRGB in turn is darker than gamma 3. REPORTER_ASSERT(r, SkColorGetR(dsts[0]) < SkColorGetR(dsts[1])); REPORTER_ASSERT(r, SkColorGetR(dsts[1]) < SkColorGetR(dsts[2])); REPORTER_ASSERT(r, SkColorGetG(dsts[0]) < SkColorGetG(dsts[1])); REPORTER_ASSERT(r, SkColorGetG(dsts[1]) < SkColorGetG(dsts[2])); }
SkColorFilter* SkColorFilter::CreateLightingFilter(SkColor mul, SkColor add) { SkColorMatrix matrix; matrix.setScale(byte_to_scale(SkColorGetR(mul)), byte_to_scale(SkColorGetG(mul)), byte_to_scale(SkColorGetB(mul)), 1); matrix.postTranslate(SkIntToScalar(SkColorGetR(add)), SkIntToScalar(SkColorGetG(add)), SkIntToScalar(SkColorGetB(add)), 0); return SkColorMatrixFilter::Create(matrix); }
/** * Removes the alpha component of an ARGB color (including unpremultiply) while * keeping the output in the same format as the input. */ static uint32_t remove_alpha_argb8888(uint32_t pmColor) { SkColor color = SkUnPreMultiply::PMColorToColor(pmColor); return SkPackARGB32NoCheck(SK_AlphaOPAQUE, SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)); }
bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { if (!this->INHERITED::setContext(device, paint, matrix)) { return false; } SkColor c; unsigned a; if (fInheritColor) { c = paint.getColor(); a = SkColorGetA(c); } else { c = fColor; a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha())); } unsigned r = SkColorGetR(c); unsigned g = SkColorGetG(c); unsigned b = SkColorGetB(c); // we want this before we apply any alpha fColor16 = SkPack888ToRGB16(r, g, b); if (a != 255) { a = SkAlpha255To256(a); r = SkAlphaMul(r, a); g = SkAlphaMul(g, a); b = SkAlphaMul(b, a); } fPMColor = SkPackARGB32(a, r, g, b); return true; }
void OsmAnd::AtlasMapRendererDebugStage_OpenGL::renderLines3D() { const auto gpuAPI = getGPUAPI(); GL_CHECK_PRESENT(glUseProgram); GL_CHECK_PRESENT(glUniformMatrix4fv); GL_CHECK_PRESENT(glUniform1f); GL_CHECK_PRESENT(glUniform2f); GL_CHECK_PRESENT(glUniform3f); GL_CHECK_PRESENT(glDrawElements); gpuAPI->glBindVertexArray_wrapper(_vaoLine3D); GL_CHECK_RESULT; // Activate program glUseProgram(_programLine3D.id); GL_CHECK_RESULT; // Set projection*view*model matrix: const auto& mProjectionView = internalState.mPerspectiveProjection * internalState.mCameraView; glUniformMatrix4fv(_programLine3D.vs.param.mProjectionViewModel, 1, GL_FALSE, glm::value_ptr(mProjectionView)); GL_CHECK_RESULT; for(const auto& primitive : constOf(_lines3D)) { const auto& line = primitive.first; const auto& color = primitive.second; // Set line color glUniform4f(_programLine3D.fs.param.color, SkColorGetR(color) / 255.0f, SkColorGetG(color) / 255.0f, SkColorGetB(color) / 255.0f, SkColorGetA(color) / 255.0f); GL_CHECK_RESULT; // Iterate over pairs of points auto itV0 = line.cbegin(); auto itV1 = itV0 + 1; for(const auto itEnd = line.cend(); itV1 != itEnd; itV0 = itV1, ++itV1) { const auto& v0 = *itV0; const auto& v1 = *itV1; // Set line coordinates glUniform4f(_programLine3D.vs.param.v0, v0.x, v0.y, v0.z, 1.0f); GL_CHECK_RESULT; glUniform4f(_programLine3D.vs.param.v1, v1.x, v1.y, v1.z, 1.0f); GL_CHECK_RESULT; // Draw the line actually glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, nullptr); GL_CHECK_RESULT; } } // Deactivate program glUseProgram(0); GL_CHECK_RESULT; // Deselect VAO gpuAPI->glBindVertexArray_wrapper(0); GL_CHECK_RESULT; }
static SkScalar RGB_to_HSV(SkColor color, HSV_Choice choice) { SkScalar red = SkIntToScalar(SkColorGetR(color)); SkScalar green = SkIntToScalar(SkColorGetG(color)); SkScalar blue = SkIntToScalar(SkColorGetB(color)); SkScalar min = SkMinScalar(SkMinScalar(red, green), blue); SkScalar value = SkMaxScalar(SkMaxScalar(red, green), blue); if (choice == kGetValue) return value/255; SkScalar delta = value - min; SkScalar saturation = value == 0 ? 0 : SkScalarDiv(delta, value); if (choice == kGetSaturation) return saturation; SkScalar hue; if (saturation == 0) hue = 0; else { SkScalar part60 = SkScalarDiv(60 * SK_Scalar1, delta); if (red == value) { hue = SkScalarMul(green - blue, part60); if (hue < 0) hue += 360 * SK_Scalar1; } else if (green == value) hue = 120 * SK_Scalar1 + SkScalarMul(blue - red, part60); else // blue == value hue = 240 * SK_Scalar1 + SkScalarMul(red - green, part60); } SkASSERT(choice == kGetHue); return hue; }
static bool write_bitmap(const char outName[], const SkBitmap& bm) { SkISize size = opaqueSize(bm); SkBitmap dst; setup_bitmap(&dst, size.width(), size.height()); for (int y = 0 ; y < dst.height(); y++) { for (int x = 0 ; x < dst.width(); x++) { SkColor color = bm.getColor(x, y); if (SkColorGetA(color) != 0xff) { int a = SkColorGetA(color); int r = SkColorGetR(color); int g = SkColorGetG(color); int b = SkColorGetB(color); if (a == 0) { r = g = b = 0; } else { r = (r * a) / 255; g = (g * a) / 255; b = (b * a) / 255; a = 255; } color = SkColorSetARGB((U8CPU)a, (U8CPU)r, (U8CPU)g, (U8CPU)b); } *dst.getAddr32(x, y) = color; } } return SkImageEncoder::EncodeFile(outName, dst, SkImageEncoder::kPNG_Type, 100); }
bool SkDrawColor::getProperty(int index, SkScriptValue* value) const { value->fType = SkType_Float; SkScalar result; switch(index) { case SK_PROPERTY(alpha): result = SkIntToScalar(SkColorGetA(color)) / 255; break; case SK_PROPERTY(blue): result = SkIntToScalar(SkColorGetB(color)); break; case SK_PROPERTY(green): result = SkIntToScalar(SkColorGetG(color)); break; case SK_PROPERTY(hue): result = RGB_to_HSV(color, kGetHue); break; case SK_PROPERTY(red): result = SkIntToScalar(SkColorGetR(color)); break; case SK_PROPERTY(saturation): result = RGB_to_HSV(color, kGetSaturation); break; case SK_PROPERTY(value): result = RGB_to_HSV(color, kGetValue); break; default: SkASSERT(0); return false; } value->fOperand.fScalar = result; return true; }
void ImageBuffer::transformColorSpace(ColorSpace srcColorSpace, ColorSpace dstColorSpace) { const uint8_t* lookUpTable = ColorSpaceUtilities::getConversionLUT(dstColorSpace, srcColorSpace); if (!lookUpTable) return; // FIXME: Disable color space conversions on accelerated canvases (for now). if (context()->isAccelerated() || !isSurfaceValid()) return; const SkBitmap& bitmap = m_surface->bitmap(); if (bitmap.isNull()) return; ASSERT(bitmap.colorType() == kN32_SkColorType); IntSize size = m_surface->size(); SkAutoLockPixels bitmapLock(bitmap); for (int y = 0; y < size.height(); ++y) { uint32_t* srcRow = bitmap.getAddr32(0, y); for (int x = 0; x < size.width(); ++x) { SkColor color = SkPMColorToColor(srcRow[x]); srcRow[x] = SkPreMultiplyARGB( SkColorGetA(color), lookUpTable[SkColorGetR(color)], lookUpTable[SkColorGetG(color)], lookUpTable[SkColorGetB(color)]); } } }
SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint) : INHERITED(device) { // cache premultiplied versions in 4444 SkPMColor c = SkPreMultiplyColor(paint.getColor()); fPMColor16 = SkPixel32ToPixel4444(c); if (paint.isDither()) { fPMColor16Other = SkDitherPixel32To4444(c); } else { fPMColor16Other = fPMColor16; } // cache raw versions in 4444 fRawColor16 = SkPackARGB4444(0xFF >> 4, SkColorGetR(c) >> 4, SkColorGetG(c) >> 4, SkColorGetB(c) >> 4); if (paint.isDither()) { fRawColor16Other = SkDitherARGB32To4444(0xFF, SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); } else { fRawColor16Other = fRawColor16; } fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other)); if (16 == fScale16) { // force the original to also be opaque fPMColor16 |= (0xF << SK_A4444_SHIFT); } }
SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, const ContextRec& rec) : INHERITED(shader, rec) { SkColor color = shader.fColor; unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha())); unsigned r = SkColorGetR(color); unsigned g = SkColorGetG(color); unsigned b = SkColorGetB(color); if (a != 255) { r = SkMulDiv255Round(r, a); g = SkMulDiv255Round(g, a); b = SkMulDiv255Round(b, a); } fPMColor = SkPackARGB32(a, r, g, b); SkColor4f c4 = SkColor4f::FromColor(shader.fColor); c4.fA *= rec.fPaint->getAlpha() / 255.0f; fPM4f = c4.premul(); fFlags = kConstInY32_Flag; if (255 == a) { fFlags |= kOpaqueAlpha_Flag; } }
// Set a bitmap shader that mimics dashing by width-on, width-off. // Returns false if it could not succeed (e.g. there was an existing shader) static bool setBitmapDash(SkPaint* paint, int width) { if (width <= 0 || paint->getShader()) return false; SkColor c = paint->getColor(); SkBitmap bm; bm.setConfig(SkBitmap::kARGB_8888_Config, 2, 1); bm.allocPixels(); bm.lockPixels(); // set the ON pixel *bm.getAddr32(0, 0) = SkPreMultiplyARGB(0xFF, SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); // set the OFF pixel *bm.getAddr32(1, 0) = 0; bm.unlockPixels(); SkMatrix matrix; matrix.setScale(SkIntToScalar(width), SK_Scalar1); SkShader* s = SkShader::CreateBitmapShader(bm, SkShader::kRepeat_TileMode, SkShader::kClamp_TileMode); s->setLocalMatrix(matrix); paint->setShader(s)->unref(); return true; }
SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, const ContextRec& rec) : INHERITED(shader, rec) { SkColor color = shader.fColor; unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha())); unsigned r = SkColorGetR(color); unsigned g = SkColorGetG(color); unsigned b = SkColorGetB(color); // we want this before we apply any alpha fColor16 = SkPack888ToRGB16(r, g, b); if (a != 255) { r = SkMulDiv255Round(r, a); g = SkMulDiv255Round(g, a); b = SkMulDiv255Round(b, a); } fPMColor = SkPackARGB32(a, r, g, b); fFlags = kConstInY32_Flag; if (255 == a) { fFlags |= kOpaqueAlpha_Flag; if (rec.fPaint->isDither() == false) { fFlags |= kHasSpan16_Flag; } } }
/* Generate Type 4 function code to map t=[0,1) to the passed gradient, clamping at the edges of the range. The generated code will be of the form: if (t < 0) { return colorData[0][r,g,b]; } else { if (t < info.fColorOffsets[1]) { return linearinterpolation(colorData[0][r,g,b], colorData[1][r,g,b]); } else { if (t < info.fColorOffsets[2]) { return linearinterpolation(colorData[1][r,g,b], colorData[2][r,g,b]); } else { ... } else { return colorData[info.fColorCount - 1][r,g,b]; } ... } } */ static void gradientFunctionCode(const SkShader::GradientInfo& info, SkString* result) { /* We want to linearly interpolate from the previous color to the next. Scale the colors from 0..255 to 0..1 and determine the multipliers for interpolation. C{r,g,b}(t, section) = t - offset_(section-1) + t * Multiplier{r,g,b}. */ static const int kColorComponents = 3; typedef SkScalar ColorTuple[kColorComponents]; SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(info.fColorCount); ColorTuple *colorData = colorDataAlloc.get(); const SkScalar scale = SkScalarInvert(SkIntToScalar(255)); for (int i = 0; i < info.fColorCount; i++) { colorData[i][0] = SkScalarMul(SkColorGetR(info.fColors[i]), scale); colorData[i][1] = SkScalarMul(SkColorGetG(info.fColors[i]), scale); colorData[i][2] = SkScalarMul(SkColorGetB(info.fColors[i]), scale); } // Clamp the initial color. result->append("dup 0 le {pop "); result->appendScalar(colorData[0][0]); result->append(" "); result->appendScalar(colorData[0][1]); result->append(" "); result->appendScalar(colorData[0][2]); result->append(" }\n"); // The gradient colors. int gradients = 0; for (int i = 1 ; i < info.fColorCount; i++) { if (info.fColorOffsets[i] == info.fColorOffsets[i - 1]) { continue; } gradients++; result->append("{dup "); result->appendScalar(info.fColorOffsets[i]); result->append(" le {"); if (info.fColorOffsets[i - 1] != 0) { result->appendScalar(info.fColorOffsets[i - 1]); result->append(" sub\n"); } interpolateColorCode(info.fColorOffsets[i] - info.fColorOffsets[i - 1], colorData[i], colorData[i - 1], result); result->append("}\n"); } // Clamp the final color. result->append("{pop "); result->appendScalar(colorData[info.fColorCount - 1][0]); result->append(" "); result->appendScalar(colorData[info.fColorCount - 1][1]); result->append(" "); result->appendScalar(colorData[info.fColorCount - 1][2]); for (int i = 0 ; i < gradients + 1; i++) { result->append("} ifelse\n"); } }
SkARGB4444_Blitter::SkARGB4444_Blitter(const SkBitmap& device, const SkPaint& paint) : INHERITED(device) { // cache premultiplied versions in 4444 SkPMColor c = SkPreMultiplyColor(paint.getColor()); fPMColor16 = SkPixel32ToPixel4444(c); if (paint.isDither()) { fPMColor16Other = SkDitherPixel32To4444(c); } else { fPMColor16Other = fPMColor16; } // cache raw versions in 4444 fRawColor16 = SkPackARGB4444(0xFF >> 4, SkColorGetR(c) >> 4, SkColorGetG(c) >> 4, SkColorGetB(c) >> 4); if (paint.isDither()) { fRawColor16Other = SkDitherARGB32To4444(0xFF, SkColorGetR(c), SkColorGetG(c), SkColorGetB(c)); } else { fRawColor16Other = fRawColor16; } #if 0 /// don't think this assertion is true, but need it be? // our dithered color will be the same or more opaque than the original // so use dithered to compute our scale SkASSERT(SkGetPackedA4444(fPMColor16Other) >= SkGetPackedA4444(fPMColor16)); #endif fScale16 = SkAlpha15To16(SkGetPackedA4444(fPMColor16Other)); if (16 == fScale16) { // force the original to also be opaque fPMColor16 |= (0xF << SK_A4444_SHIFT); } }
bool SkDrawColor::setProperty(int index, SkScriptValue& value) { SkASSERT(value.fType == SkType_Float); SkScalar scalar = value.fOperand.fScalar; switch (index) { case SK_PROPERTY(alpha): uint8_t alpha; #ifdef SK_SCALAR_IS_FLOAT alpha = scalar == SK_Scalar1 ? 255 : SkToU8((U8CPU) (scalar * 256)); #else alpha = SkToU8((scalar - (scalar >= SK_ScalarHalf)) >> 8); #endif color = SkColorSetARGB(alpha, SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)); break; case SK_PROPERTY(blue): scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color), SkColorGetG(color), SkToU8((U8CPU) scalar)); break; case SK_PROPERTY(green): scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); color = SkColorSetARGB(SkColorGetA(color), SkColorGetR(color), SkToU8((U8CPU) scalar), SkColorGetB(color)); break; case SK_PROPERTY(hue): fHue = scalar;//RGB_to_HSV(color, kGetHue); fDirty = true; break; case SK_PROPERTY(red): scalar = SkScalarClampMax(scalar, 255 * SK_Scalar1); color = SkColorSetARGB(SkColorGetA(color), SkToU8((U8CPU) scalar), SkColorGetG(color), SkColorGetB(color)); break; case SK_PROPERTY(saturation): fSaturation = scalar;//RGB_to_HSV(color, kGetSaturation); fDirty = true; break; case SK_PROPERTY(value): fValue = scalar;//RGB_to_HSV(color, kGetValue); fDirty = true; break; default: SkASSERT(0); return false; } return true; }
bool OsmAnd::AtlasMapRendererDebugStage_OpenGL::renderLines2D() { const auto gpuAPI = getGPUAPI(); const auto& internalState = getInternalState(); GL_CHECK_PRESENT(glUseProgram); GL_CHECK_PRESENT(glUniformMatrix4fv); GL_CHECK_PRESENT(glUniform1f); GL_CHECK_PRESENT(glUniform2f); GL_CHECK_PRESENT(glUniform3f); GL_CHECK_PRESENT(glDrawElements); gpuAPI->useVAO(_vaoLine2D); // Activate program glUseProgram(_programLine2D.id); GL_CHECK_RESULT; // Set projection*view*model matrix: glUniformMatrix4fv(_programLine2D.vs.param.mProjectionViewModel, 1, GL_FALSE, glm::value_ptr(internalState.mOrthographicProjection)); GL_CHECK_RESULT; for(const auto& primitive : constOf(_lines2D)) { const auto& line = primitive.first; const auto& color = primitive.second; // Set line color glUniform4f(_programLine2D.fs.param.color, SkColorGetR(color) / 255.0f, SkColorGetG(color) / 255.0f, SkColorGetB(color) / 255.0f, SkColorGetA(color) / 255.0f); GL_CHECK_RESULT; // Iterate over pairs of points auto itV0 = line.cbegin(); auto itV1 = itV0 + 1; for(const auto itEnd = line.cend(); itV1 != itEnd; itV0 = itV1, ++itV1) { const auto& v0 = *itV0; const auto& v1 = *itV1; // Set line coordinates glUniform2f(_programLine2D.vs.param.v0, v0.x, currentState.windowSize.y - v0.y); GL_CHECK_RESULT; glUniform2f(_programLine2D.vs.param.v1, v1.x, currentState.windowSize.y - v1.y); GL_CHECK_RESULT; // Draw the line actually glDrawElements(GL_LINES, 2, GL_UNSIGNED_SHORT, nullptr); GL_CHECK_RESULT; } } // Deactivate program glUseProgram(0); GL_CHECK_RESULT; gpuAPI->unuseVAO(); return true; }
SkPMColor SkPreMultiplyColor(SkColor c) { unsigned a = SkColorGetA(c); unsigned r = SkColorGetR(c); unsigned g = SkColorGetG(c); unsigned b = SkColorGetB(c); return SkPreMultiplyARGB(a, r, g, b); }
void SkBlitLCD16Row_neon(SkPMColor dst[], const uint16_t src[], SkColor color, int width, SkPMColor) { int colA = SkColorGetA(color); int colR = SkColorGetR(color); int colG = SkColorGetG(color); int colB = SkColorGetB(color); colA = SkAlpha255To256(colA); uint8x8_t vcolR, vcolG, vcolB; uint16x8_t vcolA; if (width >= 8) { vcolA = vdupq_n_u16(colA); vcolR = vdup_n_u8(colR); vcolG = vdup_n_u8(colG); vcolB = vdup_n_u8(colB); } while (width >= 8) { uint8x8x4_t vdst; uint16x8_t vmask; uint16x8_t vmaskR, vmaskG, vmaskB; vdst = vld4_u8((uint8_t*)dst); vmask = vld1q_u16(src); // Get all the color masks on 5 bits vmaskR = vshrq_n_u16(vmask, SK_R16_SHIFT); vmaskG = vshrq_n_u16(vshlq_n_u16(vmask, SK_R16_BITS), SK_B16_BITS + SK_R16_BITS + 1); vmaskB = vmask & vdupq_n_u16(SK_B16_MASK); // Upscale to 0..32 vmaskR = vmaskR + vshrq_n_u16(vmaskR, 4); vmaskG = vmaskG + vshrq_n_u16(vmaskG, 4); vmaskB = vmaskB + vshrq_n_u16(vmaskB, 4); vmaskR = vshrq_n_u16(vmaskR * vcolA, 8); vmaskG = vshrq_n_u16(vmaskG * vcolA, 8); vmaskB = vshrq_n_u16(vmaskB * vcolA, 8); vdst.val[NEON_A] = vdup_n_u8(0xFF); vdst.val[NEON_R] = SkBlend32_neon8(vcolR, vdst.val[NEON_R], vmaskR); vdst.val[NEON_G] = SkBlend32_neon8(vcolG, vdst.val[NEON_G], vmaskG); vdst.val[NEON_B] = SkBlend32_neon8(vcolB, vdst.val[NEON_B], vmaskB); vst4_u8((uint8_t*)dst, vdst); dst += 8; src += 8; width -= 8; } for (int i = 0; i < width; i++) { dst[i] = SkBlendLCD16(colA, colR, colG, colB, dst[i], src[i]); } }
/* Generate Type 4 function code to map t=[0,1) to the passed gradient, clamping at the edges of the range. The generated code will be of the form: if (t < 0) { return colorData[0][r,g,b]; } else { if (t < info.fColorOffsets[1]) { return linearinterpolation(colorData[0][r,g,b], colorData[1][r,g,b]); } else { if (t < info.fColorOffsets[2]) { return linearinterpolation(colorData[1][r,g,b], colorData[2][r,g,b]); } else { ... } else { return colorData[info.fColorCount - 1][r,g,b]; } ... } } */ static void gradient_function_code(const SkShader::GradientInfo& info, SkDynamicMemoryWStream* result) { /* We want to linearly interpolate from the previous color to the next. Scale the colors from 0..255 to 0..1 and determine the multipliers for interpolation. C{r,g,b}(t, section) = t - offset_(section-1) + t * Multiplier{r,g,b}. */ SkAutoSTMalloc<4, ColorTuple> colorDataAlloc(info.fColorCount); ColorTuple *colorData = colorDataAlloc.get(); for (int i = 0; i < info.fColorCount; i++) { colorData[i][0] = SkColorGetR(info.fColors[i]); colorData[i][1] = SkColorGetG(info.fColors[i]); colorData[i][2] = SkColorGetB(info.fColors[i]); } // Clamp the initial color. result->writeText("dup 0 le {pop "); SkPDFUtils::AppendColorComponent(colorData[0][0], result); result->writeText(" "); SkPDFUtils::AppendColorComponent(colorData[0][1], result); result->writeText(" "); SkPDFUtils::AppendColorComponent(colorData[0][2], result); result->writeText(" }\n"); // The gradient colors. int gradients = 0; for (int i = 1 ; i < info.fColorCount; i++) { if (info.fColorOffsets[i] == info.fColorOffsets[i - 1]) { continue; } gradients++; result->writeText("{dup "); SkPDFUtils::AppendScalar(info.fColorOffsets[i], result); result->writeText(" le {"); if (info.fColorOffsets[i - 1] != 0) { SkPDFUtils::AppendScalar(info.fColorOffsets[i - 1], result); result->writeText(" sub\n"); } interpolate_color_code(info.fColorOffsets[i] - info.fColorOffsets[i - 1], colorData[i], colorData[i - 1], result); result->writeText("}\n"); } // Clamp the final color. result->writeText("{pop "); SkPDFUtils::AppendColorComponent(colorData[info.fColorCount - 1][0], result); result->writeText(" "); SkPDFUtils::AppendColorComponent(colorData[info.fColorCount - 1][1], result); result->writeText(" "); SkPDFUtils::AppendColorComponent(colorData[info.fColorCount - 1][2], result); for (int i = 0 ; i < gradients + 1; i++) { result->writeText("} ifelse\n"); } }
void OsmAnd::AtlasMapRendererDebugStage_OpenGL::renderQuads3D() { const auto gpuAPI = getGPUAPI(); GL_CHECK_PRESENT(glUseProgram); GL_CHECK_PRESENT(glUniformMatrix4fv); GL_CHECK_PRESENT(glUniform1f); GL_CHECK_PRESENT(glUniform2f); GL_CHECK_PRESENT(glUniform3f); GL_CHECK_PRESENT(glDrawElements); gpuAPI->glBindVertexArray_wrapper(_vaoQuad3D); GL_CHECK_RESULT; // Activate program glUseProgram(_programQuad3D.id); GL_CHECK_RESULT; // Set projection*view*model matrix: const auto& mProjectionView = internalState.mPerspectiveProjection * internalState.mCameraView; glUniformMatrix4fv(_programQuad3D.vs.param.mProjectionViewModel, 1, GL_FALSE, glm::value_ptr(mProjectionView)); GL_CHECK_RESULT; for(const auto& primitive : constOf(_quads3D)) { const auto& p0 = std::get<0>(primitive); const auto& p1 = std::get<1>(primitive); const auto& p2 = std::get<2>(primitive); const auto& p3 = std::get<3>(primitive); const auto& color = std::get<4>(primitive); // Set quad color glUniform4f(_programQuad3D.fs.param.color, SkColorGetR(color) / 255.0f, SkColorGetG(color) / 255.0f, SkColorGetB(color) / 255.0f, SkColorGetA(color) / 255.0f); GL_CHECK_RESULT; // Set points glUniform4f(_programQuad3D.vs.param.v0, p0.x, p0.y, p0.z, 1.0f); GL_CHECK_RESULT; glUniform4f(_programQuad3D.vs.param.v1, p1.x, p1.y, p1.z, 1.0f); GL_CHECK_RESULT; glUniform4f(_programQuad3D.vs.param.v2, p2.x, p2.y, p2.z, 1.0f); GL_CHECK_RESULT; glUniform4f(_programQuad3D.vs.param.v3, p3.x, p3.y, p3.z, 1.0f); GL_CHECK_RESULT; // Draw the quad actually glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, nullptr); GL_CHECK_RESULT; } // Deactivate program glUseProgram(0); GL_CHECK_RESULT; // Deselect VAO gpuAPI->glBindVertexArray_wrapper(0); GL_CHECK_RESULT; }
static uint32_t pack_unpremul_bgra(SkColor c) { uint32_t packed; uint8_t* byte = reinterpret_cast<uint8_t*>(&packed); byte[0] = SkColorGetB(c); byte[1] = SkColorGetG(c); byte[2] = SkColorGetR(c); byte[3] = SkColorGetA(c); return packed; }
PassRefPtr<ImageData> ImageBuffer::getImageData(const IntRect& rect) const { ASSERT(context()); RefPtr<ImageData> result = ImageData::create(rect.width(), rect.height()); unsigned char* data = result->data()->data().data(); if (rect.x() < 0 || rect.y() < 0 || (rect.x() + rect.width()) > m_size.width() || (rect.y() + rect.height()) > m_size.height()) memset(data, 0, result->data()->length()); int originx = rect.x(); int destx = 0; if (originx < 0) { destx = -originx; originx = 0; } int endx = rect.x() + rect.width(); if (endx > m_size.width()) endx = m_size.width(); int numColumns = endx - originx; int originy = rect.y(); int desty = 0; if (originy < 0) { desty = -originy; originy = 0; } int endy = rect.y() + rect.height(); if (endy > m_size.height()) endy = m_size.height(); int numRows = endy - originy; const SkBitmap& bitmap = *context()->platformContext()->bitmap(); ASSERT(bitmap.config() == SkBitmap::kARGB_8888_Config); SkAutoLockPixels bitmapLock(bitmap); unsigned destBytesPerRow = 4 * rect.width(); unsigned char* destRow = data + desty * destBytesPerRow + destx * 4; for (int y = 0; y < numRows; ++y) { uint32_t* srcRow = bitmap.getAddr32(originx, originy + y); for (int x = 0; x < numColumns; ++x) { SkColor color = SkPMColorToColor(srcRow[x]); unsigned char* destPixel = &destRow[x * 4]; destPixel[0] = SkColorGetR(color); destPixel[1] = SkColorGetG(color); destPixel[2] = SkColorGetB(color); destPixel[3] = SkColorGetA(color); } destRow += destBytesPerRow; } return result; }