// Reduce to a single drawBitmapRectToRect call by folding the clipRect's into // the src and dst Rects and the saveLayer paints into the drawBitmapRectToRect's // paint. static void apply_7(SkDebugCanvas* canvas, int curCommand) { SkSaveLayerCommand* saveLayer0 = (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+2); SkSaveLayerCommand* saveLayer1 = (SkSaveLayerCommand*) canvas->getDrawCommandAt(curCommand+5); SkClipRectCommand* clip2 = (SkClipRectCommand*) canvas->getDrawCommandAt(curCommand+7); SkDrawBitmapRectCommand* dbmr = (SkDrawBitmapRectCommand*) canvas->getDrawCommandAt(curCommand+8); SkScalar newSrcLeft = dbmr->srcRect()->fLeft + clip2->rect().fLeft - dbmr->dstRect().fLeft; SkScalar newSrcTop = dbmr->srcRect()->fTop + clip2->rect().fTop - dbmr->dstRect().fTop; SkRect newSrc = SkRect::MakeXYWH(newSrcLeft, newSrcTop, clip2->rect().width(), clip2->rect().height()); dbmr->setSrcRect(newSrc); dbmr->setDstRect(clip2->rect()); SkColor color = 0xFF000000; int a0, a1; const SkPaint* saveLayerPaint0 = saveLayer0->paint(); if (NULL != saveLayerPaint0) { color = saveLayerPaint0->getColor(); a0 = SkColorGetA(color); } else { a0 = 0xFF; } const SkPaint* saveLayerPaint1 = saveLayer1->paint(); if (NULL != saveLayerPaint1) { color = saveLayerPaint1->getColor(); a1 = SkColorGetA(color); } else { a1 = 0xFF; } int newA = SkMulDiv255Round(a0, a1); SkASSERT(newA <= 0xFF); SkPaint* dbmrPaint = dbmr->paint(); if (NULL != dbmrPaint) { SkColor newColor = SkColorSetA(dbmrPaint->getColor(), newA); dbmrPaint->setColor(newColor); } else { SkColor newColor = SkColorSetA(color, newA); SkPaint newPaint; newPaint.setColor(newColor); dbmr->setPaint(newPaint); } // remove everything except the drawbitmaprect canvas->deleteDrawCommandAt(curCommand+13); // restore canvas->deleteDrawCommandAt(curCommand+12); // restore canvas->deleteDrawCommandAt(curCommand+11); // restore canvas->deleteDrawCommandAt(curCommand+10); // restore canvas->deleteDrawCommandAt(curCommand+9); // restore canvas->deleteDrawCommandAt(curCommand+7); // clipRect canvas->deleteDrawCommandAt(curCommand+6); // save canvas->deleteDrawCommandAt(curCommand+5); // saveLayer canvas->deleteDrawCommandAt(curCommand+4); // clipRect canvas->deleteDrawCommandAt(curCommand+3); // save canvas->deleteDrawCommandAt(curCommand+2); // saveLayer canvas->deleteDrawCommandAt(curCommand+1); // clipRect canvas->deleteDrawCommandAt(curCommand); // save }
virtual void onDrawContent(SkCanvas* canvas) { SkPath path; path.moveTo(SkIntToScalar(0), SkIntToScalar(50)); path.quadTo(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(50), SkIntToScalar(0)); path.lineTo(SkIntToScalar(175), SkIntToScalar(0)); path.quadTo(SkIntToScalar(200), SkIntToScalar(0), SkIntToScalar(200), SkIntToScalar(25)); path.lineTo(SkIntToScalar(200), SkIntToScalar(150)); path.quadTo(SkIntToScalar(200), SkIntToScalar(200), SkIntToScalar(150), SkIntToScalar(200)); path.lineTo(SkIntToScalar(0), SkIntToScalar(200)); path.close(); path.moveTo(SkIntToScalar(50), SkIntToScalar(50)); path.lineTo(SkIntToScalar(150), SkIntToScalar(50)); path.lineTo(SkIntToScalar(150), SkIntToScalar(125)); path.quadTo(SkIntToScalar(150), SkIntToScalar(150), SkIntToScalar(125), SkIntToScalar(150)); path.lineTo(SkIntToScalar(50), SkIntToScalar(150)); path.close(); path.setFillType(SkPath::kEvenOdd_FillType); SkColor pathColor = SK_ColorBLACK; SkPaint pathPaint; pathPaint.setAntiAlias(true); pathPaint.setColor(pathColor); SkPath clipA; clipA.moveTo(SkIntToScalar(10), SkIntToScalar(20)); clipA.lineTo(SkIntToScalar(165), SkIntToScalar(22)); clipA.lineTo(SkIntToScalar(70), SkIntToScalar(105)); clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177)); clipA.lineTo(SkIntToScalar(-5), SkIntToScalar(180)); clipA.close(); SkColor colorA = SK_ColorCYAN; SkPath clipB; clipB.moveTo(SkIntToScalar(40), SkIntToScalar(10)); clipB.lineTo(SkIntToScalar(190), SkIntToScalar(15)); clipB.lineTo(SkIntToScalar(195), SkIntToScalar(190)); clipB.lineTo(SkIntToScalar(40), SkIntToScalar(185)); clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100)); clipB.close(); SkColor colorB = SK_ColorRED; SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(0); canvas->translate(SkIntToScalar(10),SkIntToScalar(10)); canvas->drawPath(path, pathPaint); paint.setColor(colorA); canvas->drawPath(clipA, paint); paint.setColor(colorB); canvas->drawPath(clipB, paint); static const struct { SkRegion::Op fOp; const char* fName; } gOps[] = { //extra spaces in names for measureText {SkRegion::kIntersect_Op, "Isect "}, {SkRegion::kDifference_Op, "Diff " }, {SkRegion::kUnion_Op, "Union "}, {SkRegion::kXOR_Op, "Xor " }, {SkRegion::kReverseDifference_Op, "RDiff "} }; canvas->translate(0, SkIntToScalar(40)); canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4); canvas->save(); for (int invA = 0; invA < 2; ++invA) { for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) { int idx = invA * SK_ARRAY_COUNT(gOps) + op; if (!(idx % 3)) { canvas->restore(); canvas->translate(0, SkIntToScalar(250)); canvas->save(); } canvas->save(); // set clip clipA.setFillType(invA ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType); canvas->clipPath(clipA); canvas->clipPath(clipB, gOps[op].fOp); // draw path clipped canvas->drawPath(path, pathPaint); canvas->restore(); // draw path in hairline paint.setColor(pathColor); canvas->drawPath(path, paint); // draw clips in hair line paint.setColor(colorA); canvas->drawPath(clipA, paint); paint.setColor(colorB); canvas->drawPath(clipB, paint); paint.setTextSize(SkIntToScalar(20)); SkScalar txtX = SkIntToScalar(55); paint.setColor(colorA); const char* aTxt = invA ? "InverseA " : "A "; canvas->drawText(aTxt, strlen(aTxt), txtX, SkIntToScalar(220), paint); txtX += paint.measureText(aTxt, strlen(aTxt)); paint.setColor(SK_ColorBLACK); canvas->drawText(gOps[op].fName, strlen(gOps[op].fName), txtX, SkIntToScalar(220), paint); txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName)); paint.setColor(colorB); canvas->drawText("B", 1, txtX, SkIntToScalar(220), paint); canvas->translate(SkIntToScalar(250),0); } } canvas->restore(); }
void TestShell::dump() { WebScriptController::flushConsoleMessages(); // Dump the requested representation. WebFrame* frame = m_webView->mainFrame(); if (!frame) return; bool shouldDumpAsText = m_layoutTestController->shouldDumpAsText(); bool shouldGeneratePixelResults = m_layoutTestController->shouldGeneratePixelResults(); bool dumpedAnything = false; if (m_params.dumpTree) { dumpedAnything = true; m_printer->handleTextHeader(); // Text output: the test page can request different types of output // which we handle here. if (!shouldDumpAsText) { // Plain text pages should be dumped as text string mimeType = frame->dataSource()->response().mimeType().utf8(); if (mimeType == "text/plain") { shouldDumpAsText = true; shouldGeneratePixelResults = false; } } if (shouldDumpAsText) { bool recursive = m_layoutTestController->shouldDumpChildFramesAsText(); string dataUtf8 = dumpFramesAsText(frame, recursive); if (fwrite(dataUtf8.c_str(), 1, dataUtf8.size(), stdout) != dataUtf8.size()) FATAL("Short write to stdout, disk full?\n"); } else { printf("%s", frame->renderTreeAsText().utf8().data()); bool recursive = m_layoutTestController->shouldDumpChildFrameScrollPositions(); dumpFrameScrollPosition(frame, recursive); } if (m_layoutTestController->shouldDumpBackForwardList()) printf("%s", dumpAllBackForwardLists().c_str()); } if (dumpedAnything && m_params.printSeparators) m_printer->handleTextFooter(); if (m_params.dumpPixels && shouldGeneratePixelResults) { // Image output: we write the image data to the file given on the // command line (for the dump pixels argument), and the MD5 sum to // stdout. dumpedAnything = true; m_webView->layout(); if (m_layoutTestController->testRepaint()) { WebSize viewSize = m_webView->size(); int width = viewSize.width; int height = viewSize.height; if (m_layoutTestController->sweepHorizontally()) { for (WebRect column(0, 0, 1, height); column.x < width; column.x++) m_webViewHost->paintRect(column); } else { for (WebRect line(0, 0, width, 1); line.y < height; line.y++) m_webViewHost->paintRect(line); } } else m_webViewHost->paintInvalidatedRegion(); // See if we need to draw the selection bounds rect. Selection bounds // rect is the rect enclosing the (possibly transformed) selection. // The rect should be drawn after everything is laid out and painted. if (m_layoutTestController->shouldDumpSelectionRect()) { // If there is a selection rect - draw a red 1px border enclosing rect WebRect wr = frame->selectionBoundsRect(); if (!wr.isEmpty()) { // Render a red rectangle bounding selection rect SkPaint paint; paint.setColor(0xFFFF0000); // Fully opaque red paint.setStyle(SkPaint::kStroke_Style); paint.setFlags(SkPaint::kAntiAlias_Flag); paint.setStrokeWidth(1.0f); SkIRect rect; // Bounding rect rect.set(wr.x, wr.y, wr.x + wr.width, wr.y + wr.height); m_webViewHost->canvas()->drawIRect(rect, paint); } } dumpImage(m_webViewHost->canvas()); } m_printer->handleImageFooter(); m_printer->handleTestFooter(dumpedAnything); fflush(stdout); fflush(stderr); }
void drawShadowedPath(SkCanvas* canvas, const SkPath& path, const SkPoint3& zPlaneParams, const SkPaint& paint, SkScalar ambientAlpha, const SkPoint3& lightPos, SkScalar lightWidth, SkScalar spotAlpha) { if (!fShowAmbient) { ambientAlpha = 0; } if (!fShowSpot) { spotAlpha = 0; } uint32_t flags = 0; if (fUseAlt) { flags |= SkShadowFlags::kGeometricOnly_ShadowFlag; } if (fTwoPassColor) { SkColor ambientColor = SkColorSetARGB(ambientAlpha*255, 0, 0, 0); SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, lightPos, lightWidth, ambientColor, SK_ColorTRANSPARENT, flags); if (paint.getColor() != SK_ColorBLACK) { SkColor color = paint.getColor(); uint8_t max = SkTMax(SkTMax(SkColorGetR(color), SkColorGetG(color)), SkColorGetB(color)); uint8_t min = SkTMin(SkTMin(SkColorGetR(color), SkColorGetG(color)), SkColorGetB(color)); SkScalar luminance = 0.5f*(max + min) / 255.f; SkScalar alpha = (.6 - .4*luminance)*luminance*luminance + 0.3f; spotAlpha -= (alpha - 0.3f)*.5f; SkColor spotColor = SkColorSetARGB(alpha*SkColorGetA(color), SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)); SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, lightPos, lightWidth, SK_ColorTRANSPARENT, spotColor, flags); } SkColor spotGreyscale = SkColorSetARGB(spotAlpha * 255, 0, 0, 0); SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, lightPos, lightWidth, SK_ColorTRANSPARENT, spotGreyscale, flags); } else { SkColor color = paint.getColor(); SkColor baseAmbient = SkColorSetARGB(ambientAlpha*SkColorGetA(color), SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)); SkColor baseSpot = SkColorSetARGB(spotAlpha*SkColorGetA(color), SkColorGetR(color), SkColorGetG(color), SkColorGetB(color)); SkColor tonalAmbient, tonalSpot; SkShadowUtils::ComputeTonalColors(baseAmbient, baseSpot, &tonalAmbient, &tonalSpot); SkShadowUtils::DrawShadow(canvas, path, zPlaneParams, lightPos, lightWidth, tonalAmbient, tonalSpot, flags); } if (fShowObject) { canvas->drawPath(path, paint); } else { SkPaint strokePaint; strokePaint.setColor(paint.getColor()); strokePaint.setStyle(SkPaint::kStroke_Style); canvas->drawPath(path, strokePaint); } }
virtual void onDraw(SkCanvas* canvas) { SkPath path; path.moveTo(SkIntToScalar(0), SkIntToScalar(50)); path.quadTo(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(50), SkIntToScalar(0)); path.lineTo(SkIntToScalar(175), SkIntToScalar(0)); path.quadTo(SkIntToScalar(200), SkIntToScalar(0), SkIntToScalar(200), SkIntToScalar(25)); path.lineTo(SkIntToScalar(200), SkIntToScalar(150)); path.quadTo(SkIntToScalar(200), SkIntToScalar(200), SkIntToScalar(150), SkIntToScalar(200)); path.lineTo(SkIntToScalar(0), SkIntToScalar(200)); path.close(); path.moveTo(SkIntToScalar(50), SkIntToScalar(50)); path.lineTo(SkIntToScalar(150), SkIntToScalar(50)); path.lineTo(SkIntToScalar(150), SkIntToScalar(125)); path.quadTo(SkIntToScalar(150), SkIntToScalar(150), SkIntToScalar(125), SkIntToScalar(150)); path.lineTo(SkIntToScalar(50), SkIntToScalar(150)); path.close(); path.setFillType(SkPath::kEvenOdd_FillType); SkPaint pathPaint; pathPaint.setAntiAlias(true); pathPaint.setColor(gPathColor); SkPath clipA; clipA.moveTo(SkIntToScalar(10), SkIntToScalar(20)); clipA.lineTo(SkIntToScalar(165), SkIntToScalar(22)); clipA.lineTo(SkIntToScalar(70), SkIntToScalar(105)); clipA.lineTo(SkIntToScalar(165), SkIntToScalar(177)); clipA.lineTo(SkIntToScalar(-5), SkIntToScalar(180)); clipA.close(); SkPath clipB; clipB.moveTo(SkIntToScalar(40), SkIntToScalar(10)); clipB.lineTo(SkIntToScalar(190), SkIntToScalar(15)); clipB.lineTo(SkIntToScalar(195), SkIntToScalar(190)); clipB.lineTo(SkIntToScalar(40), SkIntToScalar(185)); clipB.lineTo(SkIntToScalar(155), SkIntToScalar(100)); clipB.close(); SkPaint paint; paint.setAntiAlias(true); paint.setTextSize(SkIntToScalar(20)); static const struct { SkRegion::Op fOp; const char* fName; } gOps[] = { //extra spaces in names for measureText {SkRegion::kIntersect_Op, "Isect "}, {SkRegion::kDifference_Op, "Diff " }, {SkRegion::kUnion_Op, "Union "}, {SkRegion::kXOR_Op, "Xor " }, {SkRegion::kReverseDifference_Op, "RDiff "} }; canvas->translate(SkIntToScalar(20), SkIntToScalar(20)); canvas->scale(3 * SK_Scalar1 / 4, 3 * SK_Scalar1 / 4); for (int invBits = 0; invBits < 4; ++invBits) { canvas->save(); for (size_t op = 0; op < SK_ARRAY_COUNT(gOps); ++op) { this->drawHairlines(canvas, path, clipA, clipB); bool doInvA = SkToBool(invBits & 1); bool doInvB = SkToBool(invBits & 2); canvas->save(); // set clip clipA.setFillType(doInvA ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType); clipB.setFillType(doInvB ? SkPath::kInverseEvenOdd_FillType : SkPath::kEvenOdd_FillType); canvas->clipPath(clipA, SkRegion::kIntersect_Op, fDoAAClip); canvas->clipPath(clipB, gOps[op].fOp, fDoAAClip); // draw path clipped canvas->drawPath(path, pathPaint); canvas->restore(); SkScalar txtX = SkIntToScalar(45); paint.setColor(gClipAColor); const char* aTxt = doInvA ? "InvA " : "A "; canvas->drawText(aTxt, strlen(aTxt), txtX, SkIntToScalar(220), paint); txtX += paint.measureText(aTxt, strlen(aTxt)); paint.setColor(SK_ColorBLACK); canvas->drawText(gOps[op].fName, strlen(gOps[op].fName), txtX, SkIntToScalar(220), paint); txtX += paint.measureText(gOps[op].fName, strlen(gOps[op].fName)); paint.setColor(gClipBColor); const char* bTxt = doInvB ? "InvB " : "B "; canvas->drawText(bTxt, strlen(bTxt), txtX, SkIntToScalar(220), paint); canvas->translate(SkIntToScalar(250),0); } canvas->restore(); canvas->translate(0, SkIntToScalar(250)); } }
bool OsmAnd::BinaryMapDataMetricsBitmapTileProvider_P::obtainData(const TileId tileId, const ZoomLevel zoom, std::shared_ptr<MapTiledData>& outTiledData, const IQueryController* const queryController) { BinaryMapDataProvider_Metrics::Metric_obtainData obtainDataMetric; // Obtain offline map data tile std::shared_ptr<MapTiledData> dataTile_; owner->dataProvider->obtainData(tileId, zoom, dataTile_, &obtainDataMetric); if (!dataTile_) { outTiledData.reset(); return true; } const auto dataTile = std::static_pointer_cast<BinaryMapDataTile>(dataTile_); // Prepare drawing canvas const std::shared_ptr<SkBitmap> bitmap(new SkBitmap()); bitmap->setConfig(SkBitmap::kARGB_8888_Config, owner->tileSize, owner->tileSize); if (!bitmap->allocPixels()) { LogPrintf(LogSeverityLevel::Error, "Failed to allocate buffer for ARGB8888 rasterization surface %dx%d", owner->tileSize, owner->tileSize); return false; } SkBitmapDevice target(*bitmap); SkCanvas canvas(&target); canvas.clear(SK_ColorDKGRAY); QString text; text += QString(QLatin1String("TILE %1x%2@%3\n")) .arg(tileId.x) .arg(tileId.y) .arg(zoom); text += QString(QLatin1String("BLOCKS r:%1+s:%2=%3\n")) .arg(obtainDataMetric.loadMapObjectsMetric.mapObjectsBlocksRead) .arg(obtainDataMetric.loadMapObjectsMetric.mapObjectsBlocksReferenced) .arg(obtainDataMetric.loadMapObjectsMetric.mapObjectsBlocksProcessed); text += QString(QLatin1String("OBJS u:%1+s:%2=%3\n")) .arg(obtainDataMetric.uniqueObjectsCount) .arg(obtainDataMetric.sharedObjectsCount) .arg(obtainDataMetric.objectsCount); text += QString(QLatin1String("TIME r:%1+?=%2s\n")) .arg(QString::number(obtainDataMetric.elapsedTimeForRead, 'f', 2)) .arg(QString::number(obtainDataMetric.elapsedTime, 'f', 2)); text = text.trimmed(); const auto fontSize = 16.0f; SkPaint textPaint; textPaint.setAntiAlias(true); textPaint.setTextEncoding(SkPaint::kUTF16_TextEncoding); textPaint.setTextSize(fontSize); textPaint.setColor(SK_ColorGREEN); auto topOffset = fontSize; const auto lines = text.split(QLatin1Char('\n'), QString::SkipEmptyParts); for (const auto& line : lines) { canvas.drawText( line.constData(), line.length()*sizeof(QChar), 5, topOffset, textPaint); topOffset += 1.25f * fontSize; } outTiledData.reset(new BinaryMapDataMetricsTile( dataTile, bitmap, owner->densityFactor, tileId, zoom)); return true; }
void onDraw(SkCanvas* canvas) override { SkRect dstRect = { 0, 0, SkIntToScalar(64), SkIntToScalar(64)}; static const int kMaxSrcRectSize = 1 << (SkNextLog2(gBmpSize) + 2); static const int kPadX = 30; static const int kPadY = 40; SkPaint paint; paint.setAlpha(0x20); canvas->drawBitmapRect(fLargeBitmap, SkRect::MakeIWH(gSize, gSize), &paint); canvas->translate(SK_Scalar1 * kPadX / 2, SK_Scalar1 * kPadY / 2); SkPaint blackPaint; SkScalar titleHeight = SK_Scalar1 * 24; blackPaint.setColor(SK_ColorBLACK); blackPaint.setTextSize(titleHeight); blackPaint.setAntiAlias(true); sk_tool_utils::set_portable_typeface(&blackPaint); SkString title; title.printf("Bitmap size: %d x %d", gBmpSize, gBmpSize); canvas->drawText(title.c_str(), title.size(), 0, titleHeight, blackPaint); canvas->translate(0, SK_Scalar1 * kPadY / 2 + titleHeight); int rowCount = 0; canvas->save(); for (int w = 1; w <= kMaxSrcRectSize; w *= 4) { for (int h = 1; h <= kMaxSrcRectSize; h *= 4) { SkIRect srcRect = SkIRect::MakeXYWH((gBmpSize - w) / 2, (gBmpSize - h) / 2, w, h); fProc(canvas, fImage, fLargeBitmap, srcRect, dstRect); SkString label; label.appendf("%d x %d", w, h); blackPaint.setAntiAlias(true); blackPaint.setStyle(SkPaint::kFill_Style); blackPaint.setTextSize(SK_Scalar1 * 10); SkScalar baseline = dstRect.height() + blackPaint.getTextSize() + SK_Scalar1 * 3; canvas->drawText(label.c_str(), label.size(), 0, baseline, blackPaint); blackPaint.setStyle(SkPaint::kStroke_Style); blackPaint.setStrokeWidth(SK_Scalar1); blackPaint.setAntiAlias(false); canvas->drawRect(dstRect, blackPaint); canvas->translate(dstRect.width() + SK_Scalar1 * kPadX, 0); ++rowCount; if ((dstRect.width() + kPadX) * rowCount > gSize) { canvas->restore(); canvas->translate(0, dstRect.height() + SK_Scalar1 * kPadY); canvas->save(); rowCount = 0; } } } { // test the following code path: // SkGpuDevice::drawPath() -> SkGpuDevice::drawWithMaskFilter() SkIRect srcRect; SkPaint paint; SkBitmap bm; bm = make_chessbm(5, 5); paint.setFilterQuality(kLow_SkFilterQuality); srcRect.setXYWH(1, 1, 3, 3); SkMaskFilter* mf = SkBlurMaskFilter::Create( kNormal_SkBlurStyle, SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)), SkBlurMaskFilter::kHighQuality_BlurFlag | SkBlurMaskFilter::kIgnoreTransform_BlurFlag); paint.setMaskFilter(mf)->unref(); canvas->drawBitmapRect(bm, srcRect, dstRect, &paint); } }
virtual void onDraw(SkCanvas* canvas) { if (!fInitialized) { make_bitmap(); fInitialized = true; } canvas->clear(0xFF101010); SkPaint checkPaint; checkPaint.setColor(0xFF202020); for (int y = 0; y < HEIGHT; y += 16) { for (int x = 0; x < WIDTH; x += 16) { canvas->save(); canvas->translate(SkIntToScalar(x), SkIntToScalar(y)); canvas->drawRect(SkRect::MakeXYWH(8, 0, 8, 8), checkPaint); canvas->drawRect(SkRect::MakeXYWH(0, 8, 8, 8), checkPaint); canvas->restore(); } } SkPoint3 pointLocation(0, 0, SkIntToScalar(10)); SkScalar azimuthRad = SkDegreesToRadians(SkIntToScalar(225)); SkScalar elevationRad = SkDegreesToRadians(SkIntToScalar(5)); SkPoint3 distantDirection(SkScalarMul(SkScalarCos(azimuthRad), SkScalarCos(elevationRad)), SkScalarMul(SkScalarSin(azimuthRad), SkScalarCos(elevationRad)), SkScalarSin(elevationRad)); SkPoint3 spotLocation(SkIntToScalar(-10), SkIntToScalar(-10), SkIntToScalar(20)); SkPoint3 spotTarget(SkIntToScalar(40), SkIntToScalar(40), 0); SkScalar spotExponent = SK_Scalar1; SkScalar cutoffAngle = SkIntToScalar(15); SkScalar kd = SkIntToScalar(2); SkScalar ks = SkIntToScalar(1); SkScalar shininess = SkIntToScalar(8); SkScalar surfaceScale = SkIntToScalar(1); SkColor white(0xFFFFFFFF); SkPaint paint; SkImageFilter::CropRect cropRect(SkRect::MakeXYWH(20, 10, 60, 65)); int y = 0; for (int i = 0; i < 2; i++) { const SkImageFilter::CropRect* cr = (i == 0) ? NULL : &cropRect; paint.setImageFilter(SkLightingImageFilter::CreatePointLitDiffuse(pointLocation, white, surfaceScale, kd, NULL, cr))->unref(); drawClippedBitmap(canvas, paint, 0, y); paint.setImageFilter(SkLightingImageFilter::CreateDistantLitDiffuse(distantDirection, white, surfaceScale, kd, NULL, cr))->unref(); drawClippedBitmap(canvas, paint, 110, y); paint.setImageFilter(SkLightingImageFilter::CreateSpotLitDiffuse(spotLocation, spotTarget, spotExponent, cutoffAngle, white, surfaceScale, kd, NULL, cr))->unref(); drawClippedBitmap(canvas, paint, 220, y); y += 110; paint.setImageFilter(SkLightingImageFilter::CreatePointLitSpecular(pointLocation, white, surfaceScale, ks, shininess, NULL, cr))->unref(); drawClippedBitmap(canvas, paint, 0, y); paint.setImageFilter(SkLightingImageFilter::CreateDistantLitSpecular(distantDirection, white, surfaceScale, ks, shininess, NULL, cr))->unref(); drawClippedBitmap(canvas, paint, 110, y); paint.setImageFilter(SkLightingImageFilter::CreateSpotLitSpecular(spotLocation, spotTarget, spotExponent, cutoffAngle, white, surfaceScale, ks, shininess, NULL, cr))->unref(); drawClippedBitmap(canvas, paint, 220, y); y += 110; } }
/* The srcType argument indicates what to draw for the source part. Skia * uses the implied shape of the drawing command and these modes * demonstrate that. */ void draw_mode(SkCanvas* canvas, SkXfermode* mode, SrcType srcType, SkScalar x, SkScalar y) { SkPaint p; SkMatrix m; bool restoreNeeded = false; m.setTranslate(x, y); canvas->drawBitmap(fSrcB, x, y, &p); p.setXfermode(mode); switch (srcType) { case kSmallTransparentImage_SrcType: { m.postScale(SK_ScalarHalf, SK_ScalarHalf, x, y); SkAutoCanvasRestore acr(canvas, true); canvas->concat(m); canvas->drawBitmap(fTransparent, 0, 0, &p); break; } case kQuarterClearInLayer_SrcType: { SkRect bounds = SkRect::MakeXYWH(x, y, SkIntToScalar(W), SkIntToScalar(H)); canvas->saveLayer(&bounds, &p); restoreNeeded = true; p.setXfermodeMode(SkXfermode::kSrcOver_Mode); // Fall through. } case kQuarterClear_SrcType: { SkScalar halfW = SkIntToScalar(W) / 2; SkScalar halfH = SkIntToScalar(H) / 2; p.setColor(sk_tool_utils::color_to_565(0xFF66AAFF)); SkRect r = SkRect::MakeXYWH(x + halfW, y, halfW, SkIntToScalar(H)); canvas->drawRect(r, p); p.setColor(sk_tool_utils::color_to_565(0xFFAA66FF)); r = SkRect::MakeXYWH(x, y + halfH, SkIntToScalar(W), halfH); canvas->drawRect(r, p); break; } case kRectangleWithMask_SrcType: { canvas->save(); restoreNeeded = true; SkScalar w = SkIntToScalar(W); SkScalar h = SkIntToScalar(H); SkRect r = SkRect::MakeXYWH(x, y + h / 4, w, h * 23 / 60); canvas->clipRect(r); // Fall through. } case kRectangle_SrcType: { SkScalar w = SkIntToScalar(W); SkScalar h = SkIntToScalar(H); SkRect r = SkRect::MakeXYWH(x + w / 3, y + h / 3, w * 37 / 60, h * 37 / 60); p.setColor(sk_tool_utils::color_to_565(0xFF66AAFF)); canvas->drawRect(r, p); break; } case kSmallRectangleImageWithAlpha_SrcType: m.postScale(SK_ScalarHalf, SK_ScalarHalf, x, y); // Fall through. case kRectangleImageWithAlpha_SrcType: p.setAlpha(0x88); // Fall through. case kRectangleImage_SrcType: { SkAutoCanvasRestore acr(canvas, true); canvas->concat(m); canvas->drawBitmap(fDstB, 0, 0, &p); break; } default: break; } if (restoreNeeded) { canvas->restore(); } }
static void do_fuzz(SkCanvas* canvas) { SkPath path; SkPaint paint; paint.setAntiAlias(true); for (int i=0; i<100; i++) { switch (R(33)) { case 0: paint.setColor(make_fill()); break; case 1: paint.setAlpha(gRand.nextU() & 0xFF); break; case 2: { SkXfermode::Mode mode; switch (R(3)) { case 0: mode = SkXfermode::kSrc_Mode; break; case 1: mode = SkXfermode::kXor_Mode; break; case 2: default: // silence warning mode = SkXfermode::kSrcOver_Mode; break; } paint.setXfermodeMode(mode); } break; case 3: switch (R(2)) { case 0: paint.setStrokeCap(SkPaint::kRound_Cap); break; case 1: paint.setStrokeCap(SkPaint::kButt_Cap); break; } break; case 4: switch (R(2)) { case 0: paint.setStrokeJoin(SkPaint::kRound_Join); break; case 1: paint.setStrokeJoin(SkPaint::kMiter_Join); break; } break; case 5: paint.setStrokeWidth(make_number()); break; case 6: paint.setStrokeMiter(make_number()); break; case 7: if (quick == true) break; SkSafeUnref(paint.setMaskFilter(SkBlurMaskFilter::Create(make_number(), SkBlurMaskFilter::kNormal_BlurStyle))); break; case 8: if (quick == true) break; //ctx.shadowColor = make_fill(); break; case 9: if (quick == true) break; //ctx.shadowOffsetX = make_number(); //ctx.shadowOffsetY = make_number(); break; case 10: canvas->restore(); break; case 11: canvas->rotate(make_number()); break; case 12: canvas->save(); break; case 13: canvas->scale(-1,-1); break; case 14: if (quick == true) break; if (transval == 0) { transval = make_number(); canvas->translate(transval,0); } else { canvas->translate(-transval,0); transval = 0; } break; case 15: { SkRect r; r.set(make_number(),make_number(),make_number(),make_number()); SkPaint::Style s = paint.getStyle(); paint.setStyle(SkPaint::kFill_Style); canvas->drawRect(r, paint); paint.setStyle(s); // clearrect } break; case 16: if (quick == true) break; // ctx.drawImage(imgObj,make_number(),make_number(),make_number(),make_number(),make_number(),make_number(),make_number(),make_number()); break; case 17: { SkRect r; r.set(make_number(),make_number(),make_number(),make_number()); SkPaint::Style s = paint.getStyle(); paint.setStyle(SkPaint::kFill_Style); canvas->drawRect(r, paint); paint.setStyle(s); } break; case 18: path.reset(); break; case 19: // ctx.clip() is evil. break; case 20: path.close(); break; case 21: { SkPaint::Style s = paint.getStyle(); paint.setStyle(SkPaint::kFill_Style); canvas->drawPath(path, paint); paint.setStyle(s); } break; case 22: { SkPaint::Style s = paint.getStyle(); paint.setStyle(SkPaint::kFill_Style); canvas->drawPath(path, paint); paint.setStyle(s); } break; case 23: { SkRect r; r.set(make_number(),make_number(),make_number(),make_number()); SkPaint::Style s = paint.getStyle(); paint.setStyle(SkPaint::kStroke_Style); canvas->drawRect(r, paint); paint.setStyle(s); } break; case 24: if (quick == true) break; //ctx.arc(make_number(),make_number(),make_number(),make_number(),make_number(),true); break; case 25: if (quick == true) break; //ctx.arcTo(make_number(),make_number(),make_number(),make_number(),make_number()); break; case 26: if (quick == true) break; //ctx.bezierCurveTo(make_number(),make_number(),make_number(),make_number(),make_number(),make_number()); break; case 27: path.lineTo(make_number(),make_number()); break; case 28: path.moveTo(make_number(),make_number()); break; case 29: if (quick == true) break; path.quadTo(make_number(),make_number(),make_number(),make_number()); break; case 30: { if (quick == true) break; SkMatrix matrix; set2x3(&matrix, make_number(),make_number(),make_number(),make_number(),make_number(),make_number()); canvas->concat(matrix); } break; case 31: { if (quick == true) break; SkMatrix matrix; set2x3(&matrix, make_number(),make_number(),make_number(),make_number(),make_number(),make_number()); canvas->setMatrix(matrix); } break; case 32: if (scale_large == true) { switch (scval) { case 0: canvas->scale(-1000000000,1); canvas->scale(-1000000000,1); scval = 1; break; case 1: canvas->scale(-.000000001f,1); scval = 2; break; case 2: canvas->scale(-.000000001f,1); scval = 0; break; } } break; } } }
virtual void onDraw(SkCanvas* canvas) { struct FillAndName { SkPath::FillType fFill; const char* fName; }; static const FillAndName gFills[] = { {SkPath::kWinding_FillType, "Winding"}, {SkPath::kEvenOdd_FillType, "Even / Odd"}, {SkPath::kInverseWinding_FillType, "Inverse Winding"}, {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}, }; struct StyleAndName { SkPaint::Style fStyle; const char* fName; }; static const StyleAndName gStyles[] = { {SkPaint::kFill_Style, "Fill"}, {SkPaint::kStroke_Style, "Stroke"}, {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"}, }; SkPaint titlePaint; titlePaint.setColor(SK_ColorBLACK); titlePaint.setAntiAlias(true); titlePaint.setLCDRenderText(true); titlePaint.setTextSize(15 * SK_Scalar1); const char title[] = "Empty Paths Drawn Into Rectangle Clips With " "Indicated Style and Fill"; canvas->drawText(title, strlen(title), 20 * SK_Scalar1, 20 * SK_Scalar1, titlePaint); SkRandom rand; SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1); int i = 0; canvas->save(); canvas->translate(10 * SK_Scalar1, 0); canvas->save(); for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) { for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) { if (0 == i % 4) { canvas->restore(); canvas->translate(0, rect.height() + 40 * SK_Scalar1); canvas->save(); } else { canvas->translate(rect.width() + 40 * SK_Scalar1, 0); } ++i; SkColor color = rand.nextU(); color = 0xff000000| color; // force solid this->drawEmpty(canvas, color, rect, gStyles[style].fStyle, gFills[fill].fFill); SkPaint rectPaint; rectPaint.setColor(SK_ColorBLACK); rectPaint.setStyle(SkPaint::kStroke_Style); rectPaint.setStrokeWidth(-1); rectPaint.setAntiAlias(true); canvas->drawRect(rect, rectPaint); SkPaint labelPaint; labelPaint.setColor(color); labelPaint.setAntiAlias(true); labelPaint.setLCDRenderText(true); labelPaint.setTextSize(12 * SK_Scalar1); canvas->drawText(gStyles[style].fName, strlen(gStyles[style].fName), 0, rect.height() + 15 * SK_Scalar1, labelPaint); canvas->drawText(gFills[fill].fName, strlen(gFills[fill].fName), 0, rect.height() + 28 * SK_Scalar1, labelPaint); } } canvas->restore(); canvas->restore(); }
void OsmAnd::RasterizerEnvironment_P::initializeOneWayPaint( SkPaint& paint ) { paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); paint.setColor(0xff6c70d5); }
bool OsmAnd::BinaryMapPrimitivesMetricsBitmapTileProvider_P::obtainData(const TileId tileId, const ZoomLevel zoom, std::shared_ptr<MapTiledData>& outTiledData, const IQueryController* const queryController) { BinaryMapPrimitivesProvider_Metrics::Metric_obtainData obtainDataMetric; // Obtain offline map primitives tile std::shared_ptr<MapTiledData> primitivesTile_; owner->primitivesProvider->obtainData(tileId, zoom, primitivesTile_, &obtainDataMetric, nullptr); if (!primitivesTile_) { outTiledData.reset(); return true; } const auto primitivesTile = std::static_pointer_cast<BinaryMapPrimitivesTile>(primitivesTile_); // Prepare drawing canvas const std::shared_ptr<SkBitmap> bitmap(new SkBitmap()); bitmap->setConfig(SkBitmap::kARGB_8888_Config, owner->tileSize, owner->tileSize); if (!bitmap->allocPixels()) { LogPrintf(LogSeverityLevel::Error, "Failed to allocate buffer for ARGB8888 rasterization surface %dx%d", owner->tileSize, owner->tileSize); return false; } SkBitmapDevice target(*bitmap); SkCanvas canvas(&target); canvas.clear(SK_ColorDKGRAY); QString text; text += QString(QLatin1String("TILE %1x%2@%3\n")) .arg(tileId.x) .arg(tileId.y) .arg(zoom); text += QString(QLatin1String("order %1/-%2 %3s\n")) .arg(obtainDataMetric.primitiviseMetric.orderEvaluations) .arg(obtainDataMetric.primitiviseMetric.orderRejects) .arg(QString::number(obtainDataMetric.primitiviseMetric.elapsedTimeForOrderEvaluation, 'f', 2)); text += QString(QLatin1String("polyg %1/-%2(-%3) %4s\n")) .arg(obtainDataMetric.primitiviseMetric.polygonEvaluations) .arg(obtainDataMetric.primitiviseMetric.polygonRejects) .arg(obtainDataMetric.primitiviseMetric.polygonsRejectedByArea) .arg(QString::number(obtainDataMetric.primitiviseMetric.elapsedTimeForPolygonEvaluation, 'f', 2)); text += QString(QLatin1String("polyl %1/-%2 %3s\n")) .arg(obtainDataMetric.primitiviseMetric.polylineEvaluations) .arg(obtainDataMetric.primitiviseMetric.polylineRejects) .arg(QString::number(obtainDataMetric.primitiviseMetric.elapsedTimeForPolylineEvaluation, 'f', 2)); text += QString(QLatin1String("point %1/-%2 %3s\n")) .arg(obtainDataMetric.primitiviseMetric.pointEvaluations) .arg(obtainDataMetric.primitiviseMetric.pointRejects) .arg(QString::number(obtainDataMetric.primitiviseMetric.elapsedTimeForPointEvaluation, 'f', 2)); text += QString(QLatin1String("groups %1s\n")) .arg(QString::number(obtainDataMetric.primitiviseMetric.elapsedTimeForObtainingPrimitivesGroups, 'f', 2)); text += QString(QLatin1String("d/b/c %1s/%2s/%3s\n")) .arg(QString::number(obtainDataMetric.primitiviseMetric.elapsedTimeForObtainingPrimitivesFromDetailedmap, 'f', 2)) .arg(QString::number(obtainDataMetric.primitiviseMetric.elapsedTimeForObtainingPrimitivesFromBasemap, 'f', 2)) .arg(QString::number(obtainDataMetric.primitiviseMetric.elapsedTimeForObtainingPrimitivesFromCoastlines, 'f', 2)); text += QString(QLatin1String("sym %1s\n")) .arg(QString::number(obtainDataMetric.primitiviseMetric.elapsedTimeForObtainingPrimitivesSymbols, 'f', 2)); text += QString(QLatin1String("TIME r%1+p%2+?=%3s\n")) .arg(QString::number(obtainDataMetric.obtainBinaryMapDataMetric.elapsedTime, 'f', 2)) .arg(QString::number(obtainDataMetric.primitiviseMetric.elapsedTime, 'f', 2)) .arg(QString::number(obtainDataMetric.elapsedTime, 'f', 2)); text = text.trimmed(); const auto fontSize = 16.0f; SkPaint textPaint; textPaint.setAntiAlias(true); textPaint.setTextEncoding(SkPaint::kUTF16_TextEncoding); textPaint.setTextSize(fontSize); textPaint.setColor(SK_ColorGREEN); auto topOffset = fontSize; const auto lines = text.split(QLatin1Char('\n'), QString::SkipEmptyParts); for (const auto& line : lines) { canvas.drawText( line.constData(), line.length()*sizeof(QChar), 5, topOffset, textPaint); topOffset += 1.25f * fontSize; } outTiledData.reset(new BinaryMapPrimitivesMetricsTile( primitivesTile, bitmap, owner->densityFactor, tileId, zoom)); return true; }
void WebTestThemeEngineMock::paint( blink::WebCanvas* canvas, WebThemeEngine::Part part, WebThemeEngine::State state, const blink::WebRect& rect, const WebThemeEngine::ExtraParams* extraParams) { SkIRect irect = webRectToSkIRect(rect); SkPaint paint; // Indent amounts for the check in a checkbox or radio button. const int checkIndent = 3; // Indent amounts for short and long sides of the scrollbar notches. const int notchLongOffset = 1; const int notchShortOffset = 4; const int noOffset = 0; // Indent amounts for the short and long sides of a scroll thumb box. const int thumbLongIndent = 0; const int thumbShortIndent = 2; // Indents for the crosshatch on a scroll grip. const int gripLongIndent = 3; const int gripShortIndent = 5; // Indents for the the slider track. const int sliderIndent = 2; int halfHeight = irect.height() / 2; int halfWidth = irect.width() / 2; int quarterHeight = irect.height() / 4; int quarterWidth = irect.width() / 4; int left = irect.fLeft; int right = irect.fRight; int top = irect.fTop; int bottom = irect.fBottom; switch (part) { case WebThemeEngine::PartScrollbarDownArrow: box(canvas, irect, bgColors[state]); triangle(canvas, left + quarterWidth, top + quarterHeight, right - quarterWidth, top + quarterHeight, left + halfWidth, bottom - quarterHeight, edgeColor); markState(canvas, irect, state); break; case WebThemeEngine::PartScrollbarLeftArrow: box(canvas, irect, bgColors[state]); triangle(canvas, right - quarterWidth, top + quarterHeight, right - quarterWidth, bottom - quarterHeight, left + quarterWidth, top + halfHeight, edgeColor); break; case WebThemeEngine::PartScrollbarRightArrow: box(canvas, irect, bgColors[state]); triangle(canvas, left + quarterWidth, top + quarterHeight, right - quarterWidth, top + halfHeight, left + quarterWidth, bottom - quarterHeight, edgeColor); break; case WebThemeEngine::PartScrollbarUpArrow: box(canvas, irect, bgColors[state]); triangle(canvas, left + quarterWidth, bottom - quarterHeight, left + halfWidth, top + quarterHeight, right - quarterWidth, bottom - quarterHeight, edgeColor); markState(canvas, irect, state); break; case WebThemeEngine::PartScrollbarHorizontalThumb: { // Draw a narrower box on top of the outside box. nestedBoxes(canvas, irect, thumbLongIndent, thumbShortIndent, thumbLongIndent, thumbShortIndent, bgColors[state], bgColors[state]); // Draw a horizontal crosshatch for the grip. int longOffset = halfWidth - gripLongIndent; line(canvas, left + gripLongIndent, top + halfHeight, right - gripLongIndent, top + halfHeight, edgeColor); line(canvas, left + longOffset, top + gripShortIndent, left + longOffset, bottom - gripShortIndent, edgeColor); line(canvas, right - longOffset, top + gripShortIndent, right - longOffset, bottom - gripShortIndent, edgeColor); markState(canvas, irect, state); break; } case WebThemeEngine::PartScrollbarVerticalThumb: { // Draw a shorter box on top of the outside box. nestedBoxes(canvas, irect, thumbShortIndent, thumbLongIndent, thumbShortIndent, thumbLongIndent, bgColors[state], bgColors[state]); // Draw a vertical crosshatch for the grip. int longOffset = halfHeight - gripLongIndent; line(canvas, left + halfWidth, top + gripLongIndent, left + halfWidth, bottom - gripLongIndent, edgeColor); line(canvas, left + gripShortIndent, top + longOffset, right - gripShortIndent, top + longOffset, edgeColor); line(canvas, left + gripShortIndent, bottom - longOffset, right - gripShortIndent, bottom - longOffset, edgeColor); markState(canvas, irect, state); break; } case WebThemeEngine::PartScrollbarHorizontalTrack: { int longOffset = halfHeight - notchLongOffset; int shortOffset = irect.width() - notchShortOffset; if (extraParams->scrollbarTrack.isBack) { // back, notch on left nestedBoxes(canvas, irect, noOffset, longOffset, shortOffset, longOffset, bgColors[state], edgeColor); } else { // forward, notch on right nestedBoxes(canvas, irect, shortOffset, longOffset, noOffset, longOffset, bgColors[state], edgeColor); } markState(canvas, irect, state); break; } case WebThemeEngine::PartScrollbarVerticalTrack: { int longOffset = halfWidth - notchLongOffset; int shortOffset = irect.height() - notchShortOffset; if (extraParams->scrollbarTrack.isBack) { // back, notch at top nestedBoxes(canvas, irect, longOffset, noOffset, longOffset, shortOffset, bgColors[state], edgeColor); } else { // forward, notch at bottom nestedBoxes(canvas, irect, longOffset, shortOffset, longOffset, noOffset, bgColors[state], edgeColor); } markState(canvas, irect, state); break; } case WebThemeEngine::PartCheckbox: if (extraParams->button.indeterminate) { nestedBoxes(canvas, irect, checkIndent, halfHeight, checkIndent, halfHeight, bgColors[state], edgeColor); } else if (extraParams->button.checked) { irect = validate(irect, part); nestedBoxes(canvas, irect, checkIndent, checkIndent, checkIndent, checkIndent, bgColors[state], edgeColor); } else { irect = validate(irect, part); box(canvas, irect, bgColors[state]); } break; case WebThemeEngine::PartRadio: irect = validate(irect, part); halfHeight = irect.height() / 2; if (extraParams->button.checked) { circle(canvas, irect, SkIntToScalar(halfHeight), bgColors[state]); circle(canvas, irect, SkIntToScalar(halfHeight - checkIndent), edgeColor); } else { circle(canvas, irect, SkIntToScalar(halfHeight), bgColors[state]); } break; case WebThemeEngine::PartButton: roundRect(canvas, irect, bgColors[state]); markState(canvas, irect, state); break; case WebThemeEngine::PartTextField: paint.setColor(extraParams->textField.backgroundColor); paint.setStyle(SkPaint::kFill_Style); canvas->drawIRect(irect, paint); paint.setColor(edgeColor); paint.setStyle(SkPaint::kStroke_Style); canvas->drawIRect(irect, paint); markState(canvas, irect, state); break; case WebThemeEngine::PartMenuList: if (extraParams->menuList.fillContentArea) { box(canvas, irect, extraParams->menuList.backgroundColor); } else { SkPaint paint; paint.setColor(edgeColor); paint.setStyle(SkPaint::kStroke_Style); canvas->drawIRect(irect, paint); } // clip the drop-down arrow to be inside the select box if (extraParams->menuList.arrowX - 4 > irect.fLeft) irect.fLeft = extraParams->menuList.arrowX - 4; if (extraParams->menuList.arrowX + 12 < irect.fRight) irect.fRight = extraParams->menuList.arrowX + 12; irect.fTop = extraParams->menuList.arrowY - (extraParams->menuList.arrowHeight) / 2; irect.fBottom = extraParams->menuList.arrowY + (extraParams->menuList.arrowHeight - 1) / 2; halfWidth = irect.width() / 2; quarterWidth = irect.width() / 4; if (state == WebThemeEngine::StateFocused) // FIXME: draw differenty? state = WebThemeEngine::StateNormal; box(canvas, irect, bgColors[state]); triangle(canvas, irect.fLeft + quarterWidth, irect.fTop, irect.fRight - quarterWidth, irect.fTop, irect.fLeft + halfWidth, irect.fBottom, edgeColor); break; case WebThemeEngine::PartSliderTrack: { SkIRect lirect = irect; // Draw a narrow rect for the track plus box hatches on the ends. if (state == WebThemeEngine::StateFocused) // FIXME: draw differently? state = WebThemeEngine::StateNormal; if (extraParams->slider.vertical) { lirect.inset(halfWidth - sliderIndent, noOffset); box(canvas, lirect, bgColors[state]); line(canvas, left, top, right, top, edgeColor); line(canvas, left, bottom, right, bottom, edgeColor); } else { lirect.inset(noOffset, halfHeight - sliderIndent); box(canvas, lirect, bgColors[state]); line(canvas, left, top, left, bottom, edgeColor); line(canvas, right, top, right, bottom, edgeColor); } break; } case WebThemeEngine::PartSliderThumb: if (state == WebThemeEngine::StateFocused) // FIXME: draw differently? state = WebThemeEngine::StateNormal; oval(canvas, irect, bgColors[state]); break; case WebThemeEngine::PartInnerSpinButton: { // stack half-height up and down arrows on top of each other SkIRect lirect; int halfHeight = rect.height / 2; if (extraParams->innerSpin.readOnly) state = blink::WebThemeEngine::StateDisabled; lirect.set(rect.x, rect.y, rect.x + rect.width - 1, rect.y + halfHeight - 1); box(canvas, lirect, bgColors[state]); bottom = lirect.fBottom; quarterHeight = lirect.height() / 4; triangle(canvas, left + quarterWidth, bottom - quarterHeight, right - quarterWidth, bottom - quarterHeight, left + halfWidth, top + quarterHeight, edgeColor); lirect.set(rect.x, rect.y + halfHeight, rect.x + rect.width - 1, rect.y + 2 * halfHeight - 1); top = lirect.fTop; bottom = lirect.fBottom; quarterHeight = lirect.height() / 4; box(canvas, lirect, bgColors[state]); triangle(canvas, left + quarterWidth, top + quarterHeight, right - quarterWidth, top + quarterHeight, left + halfWidth, bottom - quarterHeight, edgeColor); markState(canvas, irect, state); break; } case WebThemeEngine::PartProgressBar: { paint.setColor(bgColors[state]); paint.setStyle(SkPaint::kFill_Style); canvas->drawIRect(irect, paint); // Emulate clipping SkIRect tofill = irect; if (extraParams->progressBar.determinate) { tofill.set(extraParams->progressBar.valueRectX, extraParams->progressBar.valueRectY, extraParams->progressBar.valueRectX + extraParams->progressBar.valueRectWidth - 1, extraParams->progressBar.valueRectY + extraParams->progressBar.valueRectHeight); } tofill.intersect(irect, tofill); paint.setColor(edgeColor); paint.setStyle(SkPaint::kFill_Style); canvas->drawIRect(tofill, paint); markState(canvas, irect, state); break; } default: // FIXME: Should we do something here to indicate that we got an invalid part? // Unfortunately, we can't assert because we don't have access to WTF or base. break; } }
virtual void onDraw(SkCanvas* canvas) { this->drawBG(canvas); if (true) { SkRect r; r.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(220), SkIntToScalar(120)); SkPaint p; canvas->saveLayer(&r, &p); canvas->drawColor(0xFFFF0000); p.setAlpha(1); // or 0 p.setXfermodeMode(SkXfermode::kSrc_Mode); canvas->drawOval(r, p); canvas->restore(); return; } if (false) { SkRect r; r.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(220), SkIntToScalar(120)); SkPaint p; p.setAlpha(0x88); p.setAntiAlias(true); if (true) { canvas->saveLayer(&r, &p); p.setColor(0xFFFF0000); canvas->drawOval(r, p); canvas->restore(); } p.setColor(0xFF0000FF); r.offset(SkIntToScalar(20), SkIntToScalar(50)); canvas->drawOval(r, p); } if (false) { SkPaint p; p.setAlpha(0x88); p.setAntiAlias(true); canvas->translate(SkIntToScalar(300), 0); SkRect r; r.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(220), SkIntToScalar(60)); canvas->saveLayer(&r, &p, (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag)); // canvas->clipRect(r, SkRegion::kDifference_Op); // canvas->clipRect(r, SkRegion::kIntersect_Op); r.set(SkIntToScalar(0), SkIntToScalar(0), SkIntToScalar(220), SkIntToScalar(120)); p.setColor(SK_ColorBLUE); canvas->drawOval(r, p); canvas->restore(); return; } //canvas->translate(SkIntToScalar(20), SkIntToScalar(20)); test_fade(canvas); return; // canvas->setDrawFilter(new RedFilter)->unref(); SkRect r; SkPaint p; canvas->translate(SkIntToScalar(220), SkIntToScalar(20)); p.setAntiAlias(true); r.set(SkIntToScalar(20), SkIntToScalar(20), SkIntToScalar(220), SkIntToScalar(120)); p.setColor(SK_ColorBLUE); // p.setMaskFilter(SkBlurMaskFilter::Create(SkIntToScalar(8), SkBlurMaskFilter::kNormal_BlurStyle))->unref(); canvas->drawRect(r, p); p.setMaskFilter(NULL); SkRect bounds = r; bounds.fBottom = bounds.centerY(); canvas->saveLayer(&bounds, NULL, SkCanvas::kARGB_NoClipLayer_SaveFlag); p.setColor(SK_ColorRED); canvas->drawOval(r, p); p.setAlpha(0x80); p.setXfermodeMode(SkXfermode::kDstIn_Mode); canvas->drawRect(bounds, p); canvas->restore(); }
static void draw_zero_length_capped_paths_dbl_contour(SkCanvas* canvas, bool aa) { canvas->translate(kCellPad, kCellPad); SkImageInfo info = canvas->imageInfo().makeWH(kCellWidth, kCellHeight); auto surface = canvas->makeSurface(info); if (!surface) { surface = SkSurface::MakeRasterN32Premul(kCellWidth, kCellHeight); } SkPaint paint; paint.setColor(SK_ColorWHITE); paint.setAntiAlias(aa); paint.setStyle(SkPaint::kStroke_Style); int numFailedTests = 0; for (auto cap : kCaps) { for (auto width : kWidths) { paint.setStrokeCap(cap); paint.setStrokeWidth(width); canvas->save(); for (auto firstVerb : kSomeVerbs) { for (auto secondVerb : kSomeVerbs) { int expectedCaps = 0; SkString pathStr; pathStr.append("M 9.5 9.5 "); if (firstVerb) { pathStr.append(firstVerb); ++expectedCaps; } pathStr.append("M 40.5 9.5 "); if (secondVerb) { pathStr.append(secondVerb); ++expectedCaps; } SkPath path; SkParsePath::FromSVGString(pathStr.c_str(), &path); surface->getCanvas()->clear(SK_ColorTRANSPARENT); surface->getCanvas()->drawPath(path, paint); auto img = surface->makeImageSnapshot(); if (SkPaint::kButt_Cap == cap) { expectedCaps = 0; } if (!draw_path_cell(canvas, img.get(), expectedCaps)) { ++numFailedTests; } canvas->translate(kCellWidth + kCellPad, 0); } } canvas->restore(); canvas->translate(0, kCellHeight + kCellPad); } } canvas->drawColor(numFailedTests > 0 ? kFailureRed : kSuccessGreen); }
// test drawing with strips of fading gradient above and below static void test_fade(SkCanvas* canvas) { SkAutoCanvasRestore ar(canvas, true); SkRect r; SkPaint p; p.setAlpha(0x88); SkAutoCanvasRestore(canvas, false); // create the layers r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100)); canvas->clipRect(r); r.fBottom = SkIntToScalar(20); canvas->saveLayer(&r, NULL, (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag)); r.fTop = SkIntToScalar(80); r.fBottom = SkIntToScalar(100); canvas->saveLayer(&r, NULL, (SkCanvas::SaveFlags)(SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kFullColorLayer_SaveFlag)); // now draw the "content" if (true) { r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100)); canvas->saveLayerAlpha(&r, 0x80); SkPaint p; p.setColor(SK_ColorRED); p.setAntiAlias(true); canvas->drawOval(r, p); dump_layers("inside layer alpha", canvas); canvas->restore(); } else { r.set(0, 0, SkIntToScalar(100), SkIntToScalar(100)); SkPaint p; p.setColor(SK_ColorRED); p.setAntiAlias(true); canvas->drawOval(r, p); } // return; dump_layers("outside layer alpha", canvas); // now apply an effect SkPaint paint; make_paint(&paint); r.set(0, 0, SkIntToScalar(100), SkIntToScalar(20)); // SkDebugf("--------- draw top grad\n"); canvas->drawRect(r, paint); SkMatrix m; SkShader* s = paint.getShader(); m.setScale(SK_Scalar1, -SK_Scalar1); m.postTranslate(0, SkIntToScalar(100)); s->setLocalMatrix(m); r.fTop = SkIntToScalar(80); r.fBottom = SkIntToScalar(100); // SkDebugf("--------- draw bot grad\n"); canvas->drawRect(r, paint); }
static void test_savelayer_extraction(skiatest::Reporter* reporter) { static const int kWidth = 100; static const int kHeight = 100; // Create complex paint that the bounding box computation code can't // optimize away SkScalar blueToRedMatrix[20] = { 0 }; blueToRedMatrix[2] = blueToRedMatrix[18] = SK_Scalar1; auto blueToRed(SkColorFilter::MakeMatrixFilterRowMajor255(blueToRedMatrix)); SkAutoTUnref<SkImageFilter> filter(SkColorFilterImageFilter::Create(blueToRed.get())); SkPaint complexPaint; complexPaint.setImageFilter(filter); sk_sp<SkPicture> pict, child; SkRTreeFactory bbhFactory; { SkPictureRecorder recorder; SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight), &bbhFactory, SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag); c->saveLayer(nullptr, &complexPaint); c->restore(); child = recorder.finishRecordingAsPicture(); } // create a picture with the structure: // 1) // SaveLayer // Restore // 2) // SaveLayer // Translate // SaveLayer w/ bound // Restore // Restore // 3) // SaveLayer w/ copyable paint // Restore // 4) // SaveLayer // DrawPicture (which has a SaveLayer/Restore pair) // Restore // 5) // SaveLayer // DrawPicture with Matrix & Paint (with SaveLayer/Restore pair) // Restore { SkPictureRecorder recorder; SkCanvas* c = recorder.beginRecording(SkIntToScalar(kWidth), SkIntToScalar(kHeight), &bbhFactory, SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag); // 1) c->saveLayer(nullptr, &complexPaint); // layer #0 c->restore(); // 2) c->saveLayer(nullptr, nullptr); // layer #1 c->translate(kWidth / 2.0f, kHeight / 2.0f); SkRect r = SkRect::MakeXYWH(0, 0, kWidth/2, kHeight/2); c->saveLayer(&r, &complexPaint); // layer #2 c->restore(); c->restore(); // 3) { c->saveLayer(nullptr, &complexPaint); // layer #3 c->restore(); } SkPaint layerPaint; layerPaint.setColor(SK_ColorRED); // Non-alpha only to avoid SaveLayerDrawRestoreNooper // 4) { c->saveLayer(nullptr, &layerPaint); // layer #4 c->drawPicture(child); // layer #5 inside picture c->restore(); } // 5 { SkPaint picturePaint; SkMatrix trans; trans.setTranslate(10, 10); c->saveLayer(nullptr, &layerPaint); // layer #6 c->drawPicture(child, &trans, &picturePaint); // layer #7 inside picture c->restore(); } pict = recorder.finishRecordingAsPicture(); } // Now test out the SaveLayer extraction if (!SkCanvas::Internal_Private_GetIgnoreSaveLayerBounds()) { const SkBigPicture* bp = pict->asSkBigPicture(); REPORTER_ASSERT(reporter, bp); const SkBigPicture::AccelData* data = bp->accelData(); REPORTER_ASSERT(reporter, data); const SkLayerInfo *gpuData = static_cast<const SkLayerInfo*>(data); REPORTER_ASSERT(reporter, 8 == gpuData->numBlocks()); const SkLayerInfo::BlockInfo& info0 = gpuData->block(0); // The parent/child layers appear in reverse order const SkLayerInfo::BlockInfo& info1 = gpuData->block(2); const SkLayerInfo::BlockInfo& info2 = gpuData->block(1); const SkLayerInfo::BlockInfo& info3 = gpuData->block(3); // The parent/child layers appear in reverse order const SkLayerInfo::BlockInfo& info4 = gpuData->block(5); const SkLayerInfo::BlockInfo& info5 = gpuData->block(4); // The parent/child layers appear in reverse order const SkLayerInfo::BlockInfo& info6 = gpuData->block(7); const SkLayerInfo::BlockInfo& info7 = gpuData->block(6); REPORTER_ASSERT(reporter, nullptr == info0.fPicture); REPORTER_ASSERT(reporter, kWidth == info0.fBounds.width() && kHeight == info0.fBounds.height()); REPORTER_ASSERT(reporter, info0.fLocalMat.isIdentity()); REPORTER_ASSERT(reporter, info0.fPreMat.isIdentity()); REPORTER_ASSERT(reporter, 0 == info0.fBounds.fLeft && 0 == info0.fBounds.fTop); REPORTER_ASSERT(reporter, nullptr != info0.fPaint); REPORTER_ASSERT(reporter, !info0.fIsNested && !info0.fHasNestedLayers); REPORTER_ASSERT(reporter, nullptr == info1.fPicture); REPORTER_ASSERT(reporter, kWidth/2.0 == info1.fBounds.width() && kHeight/2.0 == info1.fBounds.height()); REPORTER_ASSERT(reporter, info1.fLocalMat.isIdentity()); REPORTER_ASSERT(reporter, info1.fPreMat.isIdentity()); REPORTER_ASSERT(reporter, kWidth/2.0 == info1.fBounds.fLeft && kHeight/2.0 == info1.fBounds.fTop); REPORTER_ASSERT(reporter, nullptr == info1.fPaint); REPORTER_ASSERT(reporter, !info1.fIsNested && info1.fHasNestedLayers); // has a nested SL REPORTER_ASSERT(reporter, nullptr == info2.fPicture); REPORTER_ASSERT(reporter, kWidth / 2 == info2.fBounds.width() && kHeight / 2 == info2.fBounds.height()); // bound reduces size REPORTER_ASSERT(reporter, !info2.fLocalMat.isIdentity()); REPORTER_ASSERT(reporter, info2.fPreMat.isIdentity()); REPORTER_ASSERT(reporter, kWidth / 2 == info2.fBounds.fLeft && // translated kHeight / 2 == info2.fBounds.fTop); REPORTER_ASSERT(reporter, nullptr != info2.fPaint); REPORTER_ASSERT(reporter, info2.fIsNested && !info2.fHasNestedLayers); // is nested REPORTER_ASSERT(reporter, nullptr == info3.fPicture); REPORTER_ASSERT(reporter, kWidth == info3.fBounds.width() && kHeight == info3.fBounds.height()); REPORTER_ASSERT(reporter, info3.fLocalMat.isIdentity()); REPORTER_ASSERT(reporter, info3.fPreMat.isIdentity()); REPORTER_ASSERT(reporter, 0 == info3.fBounds.fLeft && 0 == info3.fBounds.fTop); REPORTER_ASSERT(reporter, info3.fPaint); REPORTER_ASSERT(reporter, !info3.fIsNested && !info3.fHasNestedLayers); REPORTER_ASSERT(reporter, nullptr == info4.fPicture); REPORTER_ASSERT(reporter, kWidth == info4.fBounds.width() && kHeight == info4.fBounds.height()); REPORTER_ASSERT(reporter, 0 == info4.fBounds.fLeft && 0 == info4.fBounds.fTop); REPORTER_ASSERT(reporter, info4.fLocalMat.isIdentity()); REPORTER_ASSERT(reporter, info4.fPreMat.isIdentity()); REPORTER_ASSERT(reporter, info4.fPaint); REPORTER_ASSERT(reporter, !info4.fIsNested && info4.fHasNestedLayers); // has a nested SL REPORTER_ASSERT(reporter, child.get() == info5.fPicture); // in a child picture REPORTER_ASSERT(reporter, kWidth == info5.fBounds.width() && kHeight == info5.fBounds.height()); REPORTER_ASSERT(reporter, 0 == info5.fBounds.fLeft && 0 == info5.fBounds.fTop); REPORTER_ASSERT(reporter, info5.fLocalMat.isIdentity()); REPORTER_ASSERT(reporter, info5.fPreMat.isIdentity()); REPORTER_ASSERT(reporter, nullptr != info5.fPaint); REPORTER_ASSERT(reporter, info5.fIsNested && !info5.fHasNestedLayers); // is nested REPORTER_ASSERT(reporter, nullptr == info6.fPicture); REPORTER_ASSERT(reporter, kWidth-10 == info6.fBounds.width() && kHeight-10 == info6.fBounds.height()); REPORTER_ASSERT(reporter, 10 == info6.fBounds.fLeft && 10 == info6.fBounds.fTop); REPORTER_ASSERT(reporter, info6.fLocalMat.isIdentity()); REPORTER_ASSERT(reporter, info6.fPreMat.isIdentity()); REPORTER_ASSERT(reporter, info6.fPaint); REPORTER_ASSERT(reporter, !info6.fIsNested && info6.fHasNestedLayers); // has a nested SL REPORTER_ASSERT(reporter, child.get() == info7.fPicture); // in a child picture REPORTER_ASSERT(reporter, kWidth == info7.fBounds.width() && kHeight == info7.fBounds.height()); REPORTER_ASSERT(reporter, 0 == info7.fBounds.fLeft && 0 == info7.fBounds.fTop); REPORTER_ASSERT(reporter, info7.fLocalMat.isIdentity()); REPORTER_ASSERT(reporter, info7.fPreMat.isIdentity()); REPORTER_ASSERT(reporter, nullptr != info7.fPaint); REPORTER_ASSERT(reporter, info7.fIsNested && !info7.fHasNestedLayers); // is nested } }
void drawTextOverCanvas(RenderingContext* rc, SkCanvas* cv) { SkRect r = SkRect::MakeLTRB(0, 0, rc->getWidth(), rc->getHeight()); r.inset(-100, -100); quad_tree<TextDrawInfo*> boundsIntersect(r, 4, 0.6); SkPaint paintIcon; paintIcon.setStyle(SkPaint::kStroke_Style); paintIcon.setStrokeWidth(1); paintIcon.setColor(0xff000000); paintIcon.setFilterBitmap(true); SkPaint paintText; paintText.setStyle(SkPaint::kFill_Style); paintText.setStrokeWidth(1); paintText.setColor(0xff000000); paintText.setTextAlign(SkPaint::kCenter_Align); if(!sTypeface) sTypeface = SkTypeface::CreateFromName("Droid Serif", SkTypeface::kNormal); paintText.setTypeface(sTypeface); paintText.setAntiAlias(true); SkPaint::FontMetrics fm; // 1. Sort text using text order std::sort(rc->textToDraw.begin(), rc->textToDraw.end(), textOrder); for (uint32_t i = 0; i < rc->textToDraw.size(); i++) { TextDrawInfo* text = rc->textToDraw.at(i); if (text->text.length() > 0) { // sest text size before finding intersection (it is used there) float textSize = rc->getDensityValue(text->textSize); paintText.setTextSize(textSize); paintText.setFakeBoldText(text->bold); paintText.setColor(text->textColor); // align center y paintText.getFontMetrics(&fm); text->centerY += (-fm.fAscent); // calculate if there is intersection bool intersects = findTextIntersection(cv, rc, boundsIntersect, text, &paintText, &paintIcon); if (!intersects) { if(rc->interrupted()){ return; } if (text->drawOnPath && text->path != NULL) { if (text->textShadow > 0) { paintText.setColor(0xFFFFFFFF); paintText.setStyle(SkPaint::kStroke_Style); paintText.setStrokeWidth(2 + text->textShadow); rc->nativeOperations.Pause(); cv->drawTextOnPathHV(text->text.c_str(), text->text.length(), *text->path, text->hOffset, text->vOffset, paintText); rc->nativeOperations.Start(); // reset paintText.setStyle(SkPaint::kFill_Style); paintText.setStrokeWidth(2); paintText.setColor(text->textColor); } rc->nativeOperations.Pause(); cv->drawTextOnPathHV(text->text.c_str(), text->text.length(), *text->path, text->hOffset, text->vOffset, paintText); rc->nativeOperations.Start(); } else { if (text->shieldRes.length() > 0) { SkBitmap* ico = getCachedBitmap(rc, text->shieldRes); if (ico != NULL) { float left = text->centerX - rc->getDensityValue(ico->width() / 2) - 0.5f; float top = text->centerY - rc->getDensityValue(ico->height() / 2) - rc->getDensityValue(4.5f); SkRect r = SkRect::MakeXYWH(left, top, rc->getDensityValue(ico->width()), rc->getDensityValue(ico->height())); PROFILE_NATIVE_OPERATION(rc, cv->drawBitmapRect(*ico, (SkIRect*) NULL, r, &paintIcon)); } } drawWrappedText(rc, cv, text, textSize, paintText); } } } } }
void drawBG(SkCanvas* canvas) { SkPaint p; p.setDither(true); p.setColor(0xFF909090); canvas->drawPaint(p); }
virtual void onDraw(SkCanvas* canvas) { struct FillAndName { SkPath::FillType fFill; const char* fName; }; static const FillAndName gFills[] = { {SkPath::kWinding_FillType, "Winding"}, {SkPath::kEvenOdd_FillType, "Even / Odd"}, {SkPath::kInverseWinding_FillType, "Inverse Winding"}, {SkPath::kInverseEvenOdd_FillType, "Inverse Even / Odd"}, }; struct StyleAndName { SkPaint::Style fStyle; const char* fName; }; static const StyleAndName gStyles[] = { {SkPaint::kFill_Style, "Fill"}, {SkPaint::kStroke_Style, "Stroke"}, {SkPaint::kStrokeAndFill_Style, "Stroke And Fill"}, }; struct CapAndName { SkPaint::Cap fCap; SkPaint::Join fJoin; const char* fName; }; static const CapAndName gCaps[] = { {SkPaint::kButt_Cap, SkPaint::kBevel_Join, "Butt"}, {SkPaint::kRound_Cap, SkPaint::kRound_Join, "Round"}, {SkPaint::kSquare_Cap, SkPaint::kBevel_Join, "Square"} }; struct PathAndName { SkPath fPath; const char* fName; }; PathAndName path; path.fPath.moveTo(25*SK_Scalar1, 10*SK_Scalar1); path.fPath.cubicTo(40*SK_Scalar1, 20*SK_Scalar1, 60*SK_Scalar1, 20*SK_Scalar1, 75*SK_Scalar1, 10*SK_Scalar1); path.fPath.close(); path.fName = "moveTo-cubic-close"; SkPaint titlePaint; titlePaint.setColor(SK_ColorBLACK); titlePaint.setAntiAlias(true); sk_tool_utils::set_portable_typeface(&titlePaint); titlePaint.setTextSize(15 * SK_Scalar1); const char title[] = "Cubic Closed Drawn Into Rectangle Clips With " "Indicated Style, Fill and Linecaps, with stroke width 10"; canvas->drawText(title, strlen(title), 20 * SK_Scalar1, 20 * SK_Scalar1, titlePaint); SkRandom rand; SkRect rect = SkRect::MakeWH(100*SK_Scalar1, 30*SK_Scalar1); canvas->save(); canvas->translate(10 * SK_Scalar1, 30 * SK_Scalar1); canvas->save(); for (size_t cap = 0; cap < SK_ARRAY_COUNT(gCaps); ++cap) { if (0 < cap) { canvas->translate((rect.width() + 40 * SK_Scalar1) * SK_ARRAY_COUNT(gStyles), 0); } canvas->save(); for (size_t fill = 0; fill < SK_ARRAY_COUNT(gFills); ++fill) { if (0 < fill) { canvas->translate(0, rect.height() + 40 * SK_Scalar1); } canvas->save(); for (size_t style = 0; style < SK_ARRAY_COUNT(gStyles); ++style) { if (0 < style) { canvas->translate(rect.width() + 40 * SK_Scalar1, 0); } SkColor color = 0xff007000; this->drawPath(path.fPath, canvas, color, rect, gCaps[cap].fCap, gCaps[cap].fJoin, gStyles[style].fStyle, gFills[fill].fFill, SK_Scalar1*10); SkPaint rectPaint; rectPaint.setColor(SK_ColorBLACK); rectPaint.setStyle(SkPaint::kStroke_Style); rectPaint.setStrokeWidth(-1); rectPaint.setAntiAlias(true); canvas->drawRect(rect, rectPaint); SkPaint labelPaint; labelPaint.setColor(color); labelPaint.setAntiAlias(true); sk_tool_utils::set_portable_typeface(&labelPaint); labelPaint.setTextSize(10 * SK_Scalar1); canvas->drawText(gStyles[style].fName, strlen(gStyles[style].fName), 0, rect.height() + 12 * SK_Scalar1, labelPaint); canvas->drawText(gFills[fill].fName, strlen(gFills[fill].fName), 0, rect.height() + 24 * SK_Scalar1, labelPaint); canvas->drawText(gCaps[cap].fName, strlen(gCaps[cap].fName), 0, rect.height() + 36 * SK_Scalar1, labelPaint); } canvas->restore(); } canvas->restore(); } canvas->restore(); canvas->restore(); }
static bool drawStars(SkCanvas* canvas, int step) { SkPath path, out; const int stars = 25; int pts[stars]; static bool initialize = true; int s; for (s = 0; s < stars; ++s) { pts[s] = 4 + (s % 7); } SkPoint locs[stars]; SkScalar angles[stars]; SkScalar innerRadius[stars]; SkScalar outerRadius[stars]; const int width = 640; const int height = 480; const int margin = 30; const int minRadius = 120; const int maxInner = 800; const int maxOuter = 1153; for (s = 0; s < stars; ++s) { int starW = width - margin * 2 + (SkScalar) s * (stars - s) / stars; locs[s].fX = (int) (step * (1.3f * (s + 1) / stars) + s * 121) % (starW * 2); if (locs[s].fX > starW) { locs[s].fX = starW * 2 - locs[s].fX; } locs[s].fX += margin; int starH = height - margin * 2 + (SkScalar) s * s / stars; locs[s].fY = (int) (step * (1.7f * (s + 1) / stars) + s * 183) % (starH * 2); if (locs[s].fY > starH) { locs[s].fY = starH * 2 - locs[s].fY; } locs[s].fY += margin; angles[s] = ((step + s * 47) % (360 * 4)) * 3.1415f / 180 / 4; innerRadius[s] = (step + s * 30) % (maxInner * 2); if (innerRadius[s] > maxInner) { innerRadius[s] = (maxInner * 2) - innerRadius[s]; } innerRadius[s] = innerRadius[s] / 4 + minRadius; outerRadius[s] = (step + s * 70) % (maxOuter * 2); if (outerRadius[s] > maxOuter) { outerRadius[s] = (maxOuter * 2) - outerRadius[s]; } outerRadius[s] = outerRadius[s] / 4 + minRadius; createStar(path, innerRadius[s] / 4.0f, outerRadius[s] / 4.0f, angles[s], pts[s], locs[s]); } #define SHOW_PATH 0 #if SHOW_PATH showPath(path, "original:"); #endif #define TEST_SIMPLIFY 01 #if TEST_SIMPLIFY simplify(path, true, out); #if SHOW_PATH showPath(out, "simplified:"); #endif #endif SkPaint paint; paint.setAntiAlias(true); paint.setStyle(SkPaint::kStroke_Style); paint.setStrokeWidth(6); paint.setColor(0x1F003f7f); canvas->drawPath(path, paint); paint.setColor(0xFF305F00); paint.setStrokeWidth(1); #if TEST_SIMPLIFY canvas->drawPath(out, paint); #endif return true; }
SkPDFImageShader::SkPDFImageShader(SkPDFShader::State* state) : fState(state) { fState.get()->fImage.lockPixels(); SkMatrix finalMatrix = fState.get()->fCanvasTransform; finalMatrix.preConcat(fState.get()->fShaderTransform); SkRect surfaceBBox; surfaceBBox.set(fState.get()->fBBox); transformBBox(finalMatrix, &surfaceBBox); SkMatrix unflip; unflip.setTranslate(0, SkScalarRound(surfaceBBox.height())); unflip.preScale(SK_Scalar1, -SK_Scalar1); SkISize size = SkISize::Make(SkScalarRound(surfaceBBox.width()), SkScalarRound(surfaceBBox.height())); SkPDFDevice pattern(size, size, unflip); SkCanvas canvas(&pattern); canvas.translate(-surfaceBBox.fLeft, -surfaceBBox.fTop); finalMatrix.preTranslate(surfaceBBox.fLeft, surfaceBBox.fTop); const SkBitmap* image = &fState.get()->fImage; int width = image->width(); int height = image->height(); SkShader::TileMode tileModes[2]; tileModes[0] = fState.get()->fImageTileModes[0]; tileModes[1] = fState.get()->fImageTileModes[1]; canvas.drawBitmap(*image, 0, 0); SkRect patternBBox = SkRect::MakeXYWH(-surfaceBBox.fLeft, -surfaceBBox.fTop, width, height); // Tiling is implied. First we handle mirroring. if (tileModes[0] == SkShader::kMirror_TileMode) { SkMatrix xMirror; xMirror.setScale(-1, 1); xMirror.postTranslate(2 * width, 0); canvas.drawBitmapMatrix(*image, xMirror); patternBBox.fRight += width; } if (tileModes[1] == SkShader::kMirror_TileMode) { SkMatrix yMirror; yMirror.setScale(SK_Scalar1, -SK_Scalar1); yMirror.postTranslate(0, 2 * height); canvas.drawBitmapMatrix(*image, yMirror); patternBBox.fBottom += height; } if (tileModes[0] == SkShader::kMirror_TileMode && tileModes[1] == SkShader::kMirror_TileMode) { SkMatrix mirror; mirror.setScale(-1, -1); mirror.postTranslate(2 * width, 2 * height); canvas.drawBitmapMatrix(*image, mirror); } // Then handle Clamping, which requires expanding the pattern canvas to // cover the entire surfaceBBox. // If both x and y are in clamp mode, we start by filling in the corners. // (Which are just a rectangles of the corner colors.) if (tileModes[0] == SkShader::kClamp_TileMode && tileModes[1] == SkShader::kClamp_TileMode) { SkPaint paint; SkRect rect; rect = SkRect::MakeLTRB(surfaceBBox.fLeft, surfaceBBox.fTop, 0, 0); if (!rect.isEmpty()) { paint.setColor(image->getColor(0, 0)); canvas.drawRect(rect, paint); } rect = SkRect::MakeLTRB(width, surfaceBBox.fTop, surfaceBBox.fRight, 0); if (!rect.isEmpty()) { paint.setColor(image->getColor(width - 1, 0)); canvas.drawRect(rect, paint); } rect = SkRect::MakeLTRB(width, height, surfaceBBox.fRight, surfaceBBox.fBottom); if (!rect.isEmpty()) { paint.setColor(image->getColor(width - 1, height - 1)); canvas.drawRect(rect, paint); } rect = SkRect::MakeLTRB(surfaceBBox.fLeft, height, 0, surfaceBBox.fBottom); if (!rect.isEmpty()) { paint.setColor(image->getColor(0, height - 1)); canvas.drawRect(rect, paint); } } // Then expand the left, right, top, then bottom. if (tileModes[0] == SkShader::kClamp_TileMode) { SkIRect subset = SkIRect::MakeXYWH(0, 0, 1, height); if (surfaceBBox.fLeft < 0) { SkBitmap left; SkAssertResult(image->extractSubset(&left, subset)); SkMatrix leftMatrix; leftMatrix.setScale(-surfaceBBox.fLeft, 1); leftMatrix.postTranslate(surfaceBBox.fLeft, 0); canvas.drawBitmapMatrix(left, leftMatrix); if (tileModes[1] == SkShader::kMirror_TileMode) { leftMatrix.postScale(SK_Scalar1, -SK_Scalar1); leftMatrix.postTranslate(0, 2 * height); canvas.drawBitmapMatrix(left, leftMatrix); } patternBBox.fLeft = 0; } if (surfaceBBox.fRight > width) { SkBitmap right; subset.offset(width - 1, 0); SkAssertResult(image->extractSubset(&right, subset)); SkMatrix rightMatrix; rightMatrix.setScale(surfaceBBox.fRight - width, 1); rightMatrix.postTranslate(width, 0); canvas.drawBitmapMatrix(right, rightMatrix); if (tileModes[1] == SkShader::kMirror_TileMode) { rightMatrix.postScale(SK_Scalar1, -SK_Scalar1); rightMatrix.postTranslate(0, 2 * height); canvas.drawBitmapMatrix(right, rightMatrix); } patternBBox.fRight = surfaceBBox.width(); } } if (tileModes[1] == SkShader::kClamp_TileMode) { SkIRect subset = SkIRect::MakeXYWH(0, 0, width, 1); if (surfaceBBox.fTop < 0) { SkBitmap top; SkAssertResult(image->extractSubset(&top, subset)); SkMatrix topMatrix; topMatrix.setScale(SK_Scalar1, -surfaceBBox.fTop); topMatrix.postTranslate(0, surfaceBBox.fTop); canvas.drawBitmapMatrix(top, topMatrix); if (tileModes[0] == SkShader::kMirror_TileMode) { topMatrix.postScale(-1, 1); topMatrix.postTranslate(2 * width, 0); canvas.drawBitmapMatrix(top, topMatrix); } patternBBox.fTop = 0; } if (surfaceBBox.fBottom > height) { SkBitmap bottom; subset.offset(0, height - 1); SkAssertResult(image->extractSubset(&bottom, subset)); SkMatrix bottomMatrix; bottomMatrix.setScale(SK_Scalar1, surfaceBBox.fBottom - height); bottomMatrix.postTranslate(0, height); canvas.drawBitmapMatrix(bottom, bottomMatrix); if (tileModes[0] == SkShader::kMirror_TileMode) { bottomMatrix.postScale(-1, 1); bottomMatrix.postTranslate(2 * width, 0); canvas.drawBitmapMatrix(bottom, bottomMatrix); } patternBBox.fBottom = surfaceBBox.height(); } } SkRefPtr<SkPDFArray> patternBBoxArray = new SkPDFArray; patternBBoxArray->unref(); // SkRefPtr and new both took a reference. patternBBoxArray->reserve(4); patternBBoxArray->appendScalar(patternBBox.fLeft); patternBBoxArray->appendScalar(patternBBox.fTop); patternBBoxArray->appendScalar(patternBBox.fRight); patternBBoxArray->appendScalar(patternBBox.fBottom); // Put the canvas into the pattern stream (fContent). SkRefPtr<SkStream> content = pattern.content(); content->unref(); // SkRefPtr and content() both took a reference. pattern.getResources(&fResources); setData(content.get()); insertName("Type", "Pattern"); insertInt("PatternType", 1); insertInt("PaintType", 1); insertInt("TilingType", 1); insert("BBox", patternBBoxArray.get()); insertScalar("XStep", patternBBox.width()); insertScalar("YStep", patternBBox.height()); insert("Resources", pattern.getResourceDict()); insert("Matrix", SkPDFUtils::MatrixToArray(finalMatrix))->unref(); fState.get()->fImage.unlockPixels(); }
virtual void onDraw(SkCanvas* canvas) { if (!fInitialized) { this->make_checkerboard(); this->make_gradient_circle(64, 64); fInitialized = true; } canvas->clear(0x00000000); SkAutoTUnref<SkImageFilter> gradient(SkBitmapSource::Create(fGradientCircle)); SkAutoTUnref<SkImageFilter> checkerboard(SkBitmapSource::Create(fCheckerboard)); SkAutoTUnref<SkShader> noise(SkPerlinNoiseShader::CreateFractalNoise( SkDoubleToScalar(0.1), SkDoubleToScalar(0.05), 1, 0)); SkMatrix resizeMatrix; resizeMatrix.setScale(RESIZE_FACTOR_X, RESIZE_FACTOR_Y); SkImageFilter* filters[] = { SkBlurImageFilter::Create(SkIntToScalar(12), SkIntToScalar(12)), SkDropShadowImageFilter::Create(SkIntToScalar(10), SkIntToScalar(10), SkIntToScalar(3), SK_ColorGREEN), SkDisplacementMapEffect::Create(SkDisplacementMapEffect::kR_ChannelSelectorType, SkDisplacementMapEffect::kR_ChannelSelectorType, SkIntToScalar(12), gradient.get(), checkerboard.get()), SkDilateImageFilter::Create(2, 2, checkerboard.get()), SkErodeImageFilter::Create(2, 2, checkerboard.get()), SkOffsetImageFilter::Create(SkIntToScalar(-16), SkIntToScalar(32)), SkMatrixImageFilter::Create(resizeMatrix, SkPaint::kNone_FilterLevel), SkRectShaderImageFilter::Create(noise), }; SkRect r = SkRect::MakeWH(SkIntToScalar(64), SkIntToScalar(64)); SkScalar margin = SkIntToScalar(16); SkRect bounds = r; bounds.outset(margin, margin); for (int xOffset = 0; xOffset < 80; xOffset += 16) { canvas->save(); bounds.fLeft = SkIntToScalar(xOffset); for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) { SkPaint paint; paint.setColor(SK_ColorWHITE); paint.setImageFilter(filters[i]); paint.setAntiAlias(true); canvas->save(); canvas->clipRect(bounds); if (5 == i) { canvas->translate(SkIntToScalar(16), SkIntToScalar(-32)); } else if (6 == i) { canvas->scale(SkScalarInvert(RESIZE_FACTOR_X), SkScalarInvert(RESIZE_FACTOR_Y)); } canvas->drawCircle(r.centerX(), r.centerY(), SkScalarDiv(r.width()*2, SkIntToScalar(5)), paint); canvas->restore(); canvas->translate(r.width() + margin, 0); } canvas->restore(); canvas->translate(0, r.height() + margin); } for (size_t i = 0; i < SK_ARRAY_COUNT(filters); ++i) { SkSafeUnref(filters[i]); } }
void makePaints() { { // no AA SkPaint p; p.setColor(SK_ColorWHITE); fPaints.push_back(p); } { // AA SkPaint p; p.setColor(SK_ColorWHITE); p.setAntiAlias(true); fPaints.push_back(p); } { // AA with translucent SkPaint p; p.setColor(SK_ColorWHITE); p.setAntiAlias(true); p.setAlpha(0x66); fPaints.push_back(p); } { // AA with mask filter SkPaint p; p.setColor(SK_ColorWHITE); p.setAntiAlias(true); SkMaskFilter* mf = SkBlurMaskFilter::Create( kNormal_SkBlurStyle, SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(5)), SkBlurMaskFilter::kHighQuality_BlurFlag); p.setMaskFilter(mf)->unref(); fPaints.push_back(p); } { // AA with radial shader SkPaint p; p.setColor(SK_ColorWHITE); p.setAntiAlias(true); SkPoint center = SkPoint::Make(SkIntToScalar(-5), SkIntToScalar(30)); SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN }; SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 }; SkShader* s = SkGradientShader::CreateRadial(center, SkIntToScalar(20), colors, pos, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode); p.setShader(s)->unref(); fPaints.push_back(p); } { // AA with blur SkPaint p; p.setColor(SK_ColorWHITE); p.setAntiAlias(true); SkDrawLooper* shadowLooper = SkBlurDrawLooper::Create(SK_ColorWHITE, SkBlurMask::ConvertRadiusToSigma(SkIntToScalar(10)), SkIntToScalar(5), SkIntToScalar(10), SkBlurDrawLooper::kIgnoreTransform_BlurFlag | SkBlurDrawLooper::kOverrideColor_BlurFlag | SkBlurDrawLooper::kHighQuality_BlurFlag); SkAutoUnref aurL0(shadowLooper); p.setLooper(shadowLooper); fPaints.push_back(p); } { // AA with stroke style SkPaint p; p.setColor(SK_ColorWHITE); p.setAntiAlias(true); p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(SkIntToScalar(3)); fPaints.push_back(p); } { // AA with bevel-stroke style SkPaint p; p.setColor(SK_ColorWHITE); p.setAntiAlias(true); p.setStyle(SkPaint::kStroke_Style); p.setStrokeJoin(SkPaint::kBevel_Join); p.setStrokeWidth(SkIntToScalar(3)); fPaints.push_back(p); } { // AA with round-stroke style SkPaint p; p.setColor(SK_ColorWHITE); p.setAntiAlias(true); p.setStyle(SkPaint::kStroke_Style); p.setStrokeJoin(SkPaint::kRound_Join); p.setStrokeWidth(SkIntToScalar(3)); fPaints.push_back(p); } { // AA with stroke style, width = 0 SkPaint p; p.setColor(SK_ColorWHITE); p.setAntiAlias(true); p.setStyle(SkPaint::kStroke_Style); fPaints.push_back(p); } { // AA with stroke style, width wider than rect width and/or height SkPaint p; p.setColor(SK_ColorWHITE); p.setAntiAlias(true); p.setStyle(SkPaint::kStroke_Style); p.setStrokeWidth(SkIntToScalar(40)); fPaints.push_back(p); } { // AA with stroke and fill style SkPaint p; p.setColor(SK_ColorWHITE); p.setAntiAlias(true); p.setStyle(SkPaint::kStrokeAndFill_Style); p.setStrokeWidth(SkIntToScalar(2)); fPaints.push_back(p); } }
SkPDFImageShader* SkPDFImageShader::Create( SkPDFCanon* canon, SkScalar dpi, SkAutoTDelete<SkPDFShader::State>* autoState) { const SkPDFShader::State& state = **autoState; state.fImage.lockPixels(); // The image shader pattern cell will be drawn into a separate device // in pattern cell space (no scaling on the bitmap, though there may be // translations so that all content is in the device, coordinates > 0). // Map clip bounds to shader space to ensure the device is large enough // to handle fake clamping. SkMatrix finalMatrix = state.fCanvasTransform; finalMatrix.preConcat(state.fShaderTransform); SkRect deviceBounds; deviceBounds.set(state.fBBox); if (!inverse_transform_bbox(finalMatrix, &deviceBounds)) { return NULL; } const SkBitmap* image = &state.fImage; SkRect bitmapBounds; image->getBounds(&bitmapBounds); // For tiling modes, the bounds should be extended to include the bitmap, // otherwise the bitmap gets clipped out and the shader is empty and awful. // For clamp modes, we're only interested in the clip region, whether // or not the main bitmap is in it. SkShader::TileMode tileModes[2]; tileModes[0] = state.fImageTileModes[0]; tileModes[1] = state.fImageTileModes[1]; if (tileModes[0] != SkShader::kClamp_TileMode || tileModes[1] != SkShader::kClamp_TileMode) { deviceBounds.join(bitmapBounds); } SkISize size = SkISize::Make(SkScalarRoundToInt(deviceBounds.width()), SkScalarRoundToInt(deviceBounds.height())); SkAutoTUnref<SkPDFDevice> patternDevice( SkPDFDevice::CreateUnflipped(size, dpi, canon)); SkCanvas canvas(patternDevice.get()); SkRect patternBBox; image->getBounds(&patternBBox); // Translate the canvas so that the bitmap origin is at (0, 0). canvas.translate(-deviceBounds.left(), -deviceBounds.top()); patternBBox.offset(-deviceBounds.left(), -deviceBounds.top()); // Undo the translation in the final matrix finalMatrix.preTranslate(deviceBounds.left(), deviceBounds.top()); // If the bitmap is out of bounds (i.e. clamp mode where we only see the // stretched sides), canvas will clip this out and the extraneous data // won't be saved to the PDF. canvas.drawBitmap(*image, 0, 0); SkScalar width = SkIntToScalar(image->width()); SkScalar height = SkIntToScalar(image->height()); // Tiling is implied. First we handle mirroring. if (tileModes[0] == SkShader::kMirror_TileMode) { SkMatrix xMirror; xMirror.setScale(-1, 1); xMirror.postTranslate(2 * width, 0); drawBitmapMatrix(&canvas, *image, xMirror); patternBBox.fRight += width; } if (tileModes[1] == SkShader::kMirror_TileMode) { SkMatrix yMirror; yMirror.setScale(SK_Scalar1, -SK_Scalar1); yMirror.postTranslate(0, 2 * height); drawBitmapMatrix(&canvas, *image, yMirror); patternBBox.fBottom += height; } if (tileModes[0] == SkShader::kMirror_TileMode && tileModes[1] == SkShader::kMirror_TileMode) { SkMatrix mirror; mirror.setScale(-1, -1); mirror.postTranslate(2 * width, 2 * height); drawBitmapMatrix(&canvas, *image, mirror); } // Then handle Clamping, which requires expanding the pattern canvas to // cover the entire surfaceBBox. // If both x and y are in clamp mode, we start by filling in the corners. // (Which are just a rectangles of the corner colors.) if (tileModes[0] == SkShader::kClamp_TileMode && tileModes[1] == SkShader::kClamp_TileMode) { SkPaint paint; SkRect rect; rect = SkRect::MakeLTRB(deviceBounds.left(), deviceBounds.top(), 0, 0); if (!rect.isEmpty()) { paint.setColor(image->getColor(0, 0)); canvas.drawRect(rect, paint); } rect = SkRect::MakeLTRB(width, deviceBounds.top(), deviceBounds.right(), 0); if (!rect.isEmpty()) { paint.setColor(image->getColor(image->width() - 1, 0)); canvas.drawRect(rect, paint); } rect = SkRect::MakeLTRB(width, height, deviceBounds.right(), deviceBounds.bottom()); if (!rect.isEmpty()) { paint.setColor(image->getColor(image->width() - 1, image->height() - 1)); canvas.drawRect(rect, paint); } rect = SkRect::MakeLTRB(deviceBounds.left(), height, 0, deviceBounds.bottom()); if (!rect.isEmpty()) { paint.setColor(image->getColor(0, image->height() - 1)); canvas.drawRect(rect, paint); } } // Then expand the left, right, top, then bottom. if (tileModes[0] == SkShader::kClamp_TileMode) { SkIRect subset = SkIRect::MakeXYWH(0, 0, 1, image->height()); if (deviceBounds.left() < 0) { SkBitmap left; SkAssertResult(image->extractSubset(&left, subset)); SkMatrix leftMatrix; leftMatrix.setScale(-deviceBounds.left(), 1); leftMatrix.postTranslate(deviceBounds.left(), 0); drawBitmapMatrix(&canvas, left, leftMatrix); if (tileModes[1] == SkShader::kMirror_TileMode) { leftMatrix.postScale(SK_Scalar1, -SK_Scalar1); leftMatrix.postTranslate(0, 2 * height); drawBitmapMatrix(&canvas, left, leftMatrix); } patternBBox.fLeft = 0; } if (deviceBounds.right() > width) { SkBitmap right; subset.offset(image->width() - 1, 0); SkAssertResult(image->extractSubset(&right, subset)); SkMatrix rightMatrix; rightMatrix.setScale(deviceBounds.right() - width, 1); rightMatrix.postTranslate(width, 0); drawBitmapMatrix(&canvas, right, rightMatrix); if (tileModes[1] == SkShader::kMirror_TileMode) { rightMatrix.postScale(SK_Scalar1, -SK_Scalar1); rightMatrix.postTranslate(0, 2 * height); drawBitmapMatrix(&canvas, right, rightMatrix); } patternBBox.fRight = deviceBounds.width(); } } if (tileModes[1] == SkShader::kClamp_TileMode) { SkIRect subset = SkIRect::MakeXYWH(0, 0, image->width(), 1); if (deviceBounds.top() < 0) { SkBitmap top; SkAssertResult(image->extractSubset(&top, subset)); SkMatrix topMatrix; topMatrix.setScale(SK_Scalar1, -deviceBounds.top()); topMatrix.postTranslate(0, deviceBounds.top()); drawBitmapMatrix(&canvas, top, topMatrix); if (tileModes[0] == SkShader::kMirror_TileMode) { topMatrix.postScale(-1, 1); topMatrix.postTranslate(2 * width, 0); drawBitmapMatrix(&canvas, top, topMatrix); } patternBBox.fTop = 0; } if (deviceBounds.bottom() > height) { SkBitmap bottom; subset.offset(0, image->height() - 1); SkAssertResult(image->extractSubset(&bottom, subset)); SkMatrix bottomMatrix; bottomMatrix.setScale(SK_Scalar1, deviceBounds.bottom() - height); bottomMatrix.postTranslate(0, height); drawBitmapMatrix(&canvas, bottom, bottomMatrix); if (tileModes[0] == SkShader::kMirror_TileMode) { bottomMatrix.postScale(-1, 1); bottomMatrix.postTranslate(2 * width, 0); drawBitmapMatrix(&canvas, bottom, bottomMatrix); } patternBBox.fBottom = deviceBounds.height(); } } // Put the canvas into the pattern stream (fContent). SkAutoTDelete<SkStreamAsset> content(patternDevice->content()); SkPDFImageShader* imageShader = SkNEW_ARGS(SkPDFImageShader, (autoState->detach())); imageShader->setData(content.get()); SkAutoTUnref<SkPDFDict> resourceDict( patternDevice->createResourceDict()); populate_tiling_pattern_dict(imageShader, patternBBox, resourceDict.get(), finalMatrix); imageShader->fShaderState->fImage.unlockPixels(); canon->addImageShader(imageShader); return imageShader; }
static void do_draw(SkCanvas* canvas, const SkRect& r) { SkPaint paint; paint.setBlendMode(SkBlendMode::kSrc); paint.setColor(0x800000FF); canvas->drawRect(r, paint); }
void onDraw(SkCanvas* canvas) override { SkRandom rand(1); canvas->translate(20 * SK_Scalar1, 20 * SK_Scalar1); SkRect oval = SkRect::MakeLTRB(-20, -30, 20, 30); const SkScalar kXStart = 60.0f; const SkScalar kYStart = 80.0f; const int kXStep = 150; const int kYStep = 160; int maxX = fMatrices.count(); SkPaint rectPaint; rectPaint.setAntiAlias(true); rectPaint.setStyle(SkPaint::kStroke_Style); rectPaint.setStrokeWidth(SkIntToScalar(0)); rectPaint.setColor(sk_tool_utils::color_to_565(SK_ColorLTGRAY)); int testCount = 0; for (int i = 0; i < fPaints.count(); ++i) { for (int j = 0; j < fMatrices.count(); ++j) { canvas->save(); SkMatrix mat = fMatrices[j]; // position the oval, and make it at off-integer coords. mat.postTranslate(kXStart + SK_Scalar1 * kXStep * (testCount % maxX) + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * (testCount / maxX) + 3 * SK_Scalar1 / 4); canvas->concat(mat); SkColor color = genColor(&rand); fPaints[i].setColor(color); canvas->drawRect(oval, rectPaint); canvas->drawOval(oval, fPaints[i]); canvas->restore(); ++testCount; } } // special cases // non-scaled tall and skinny oval for (int i = 0; i < fPaints.count(); ++i) { SkRect oval = SkRect::MakeLTRB(-20, -60, 20, 60); canvas->save(); // position the oval, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.55f + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4); SkColor color = genColor(&rand); fPaints[i].setColor(color); canvas->drawRect(oval, rectPaint); canvas->drawOval(oval, fPaints[i]); canvas->restore(); } // non-scaled wide and short oval for (int i = 0; i < fPaints.count(); ++i) { SkRect oval = SkRect::MakeLTRB(-80, -30, 80, 30); canvas->save(); // position the oval, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 4 + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 + SK_ScalarHalf * kYStep); SkColor color = genColor(&rand); fPaints[i].setColor(color); canvas->drawRect(oval, rectPaint); canvas->drawOval(oval, fPaints[i]); canvas->restore(); } // super skinny oval for (int i = 0; i < fPaints.count(); ++i) { SkRect oval = SkRect::MakeLTRB(0, -60, 1, 60); canvas->save(); // position the oval, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 3.25f + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4); SkColor color = genColor(&rand); fPaints[i].setColor(color); canvas->drawOval(oval, fPaints[i]); canvas->restore(); } // super short oval for (int i = 0; i < fPaints.count(); ++i) { SkRect oval = SkRect::MakeLTRB(-80, -1, 80, 0); canvas->save(); // position the oval, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 2.5f + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 + SK_ScalarHalf * kYStep); SkColor color = genColor(&rand); fPaints[i].setColor(color); canvas->drawOval(oval, fPaints[i]); canvas->restore(); } // radial gradient SkPoint center = SkPoint::Make(SkIntToScalar(0), SkIntToScalar(0)); SkColor colors[] = { SK_ColorBLUE, SK_ColorRED, SK_ColorGREEN }; SkScalar pos[] = { 0, SK_ScalarHalf, SK_Scalar1 }; auto shader = SkGradientShader::MakeRadial(center, 20, colors, pos, SK_ARRAY_COUNT(colors), SkShader::kClamp_TileMode); for (int i = 0; i < fPaints.count(); ++i) { canvas->save(); // position the path, and make it at off-integer coords. canvas->translate(kXStart + SK_Scalar1 * kXStep * 0 + SK_Scalar1 / 4, kYStart + SK_Scalar1 * kYStep * i + 3 * SK_Scalar1 / 4 + SK_ScalarHalf * kYStep); SkColor color = genColor(&rand); fPaints[i].setColor(color); fPaints[i].setShader(shader); canvas->drawRect(oval, rectPaint); canvas->drawOval(oval, fPaints[i]); fPaints[i].setShader(nullptr); canvas->restore(); } }
static void SetPaintPattern(SkPaint& aPaint, const Pattern& aPattern, TempBitmap& aTmpBitmap, Float aAlpha = 1.0) { switch (aPattern.GetType()) { case PatternType::COLOR: { Color color = static_cast<const ColorPattern&>(aPattern).mColor; aPaint.setColor(ColorToSkColor(color, aAlpha)); break; } case PatternType::LINEAR_GRADIENT: { const LinearGradientPattern& pat = static_cast<const LinearGradientPattern&>(aPattern); GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get()); SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode); if (stops->mCount >= 2) { SkPoint points[2]; points[0] = SkPoint::Make(SkFloatToScalar(pat.mBegin.x), SkFloatToScalar(pat.mBegin.y)); points[1] = SkPoint::Make(SkFloatToScalar(pat.mEnd.x), SkFloatToScalar(pat.mEnd.y)); SkShader* shader = SkGradientShader::CreateLinear(points, &stops->mColors.front(), &stops->mPositions.front(), stops->mCount, mode); if (shader) { SkMatrix mat; GfxMatrixToSkiaMatrix(pat.mMatrix, mat); shader->setLocalMatrix(mat); SkSafeUnref(aPaint.setShader(shader)); } } else { aPaint.setColor(SkColorSetARGB(0, 0, 0, 0)); } break; } case PatternType::RADIAL_GRADIENT: { const RadialGradientPattern& pat = static_cast<const RadialGradientPattern&>(aPattern); GradientStopsSkia *stops = static_cast<GradientStopsSkia*>(pat.mStops.get()); SkShader::TileMode mode = ExtendModeToTileMode(stops->mExtendMode); if (stops->mCount >= 2) { SkPoint points[2]; points[0] = SkPoint::Make(SkFloatToScalar(pat.mCenter1.x), SkFloatToScalar(pat.mCenter1.y)); points[1] = SkPoint::Make(SkFloatToScalar(pat.mCenter2.x), SkFloatToScalar(pat.mCenter2.y)); SkShader* shader = SkGradientShader::CreateTwoPointConical(points[0], SkFloatToScalar(pat.mRadius1), points[1], SkFloatToScalar(pat.mRadius2), &stops->mColors.front(), &stops->mPositions.front(), stops->mCount, mode); if (shader) { SkMatrix mat; GfxMatrixToSkiaMatrix(pat.mMatrix, mat); shader->setLocalMatrix(mat); SkSafeUnref(aPaint.setShader(shader)); } } else { aPaint.setColor(SkColorSetARGB(0, 0, 0, 0)); } break; } case PatternType::SURFACE: { const SurfacePattern& pat = static_cast<const SurfacePattern&>(aPattern); aTmpBitmap = GetBitmapForSurface(pat.mSurface); const SkBitmap& bitmap = aTmpBitmap.mBitmap; SkShader::TileMode mode = ExtendModeToTileMode(pat.mExtendMode); SkShader* shader = SkShader::CreateBitmapShader(bitmap, mode, mode); SkMatrix mat; GfxMatrixToSkiaMatrix(pat.mMatrix, mat); shader->setLocalMatrix(mat); SkSafeUnref(aPaint.setShader(shader)); if (pat.mFilter == Filter::POINT) { aPaint.setFilterBitmap(false); } break; } } }
void OsmAnd::MapRasterizer_P::rasterize( const AreaI area31, const std::shared_ptr<const MapPrimitiviser::PrimitivisedObjects>& primitivisedObjects, SkCanvas& canvas, const bool fillBackground, const AreaI* const pDestinationArea, MapRasterizer_Metrics::Metric_rasterize* const metric, const std::shared_ptr<const IQueryController>& queryController) { const Stopwatch totalStopwatch(metric != nullptr); const Context context( area31, primitivisedObjects, pDestinationArea ? *pDestinationArea : AreaI(0, 0, canvas.imageInfo().height(), canvas.imageInfo().width())); // Deal with background if (fillBackground) { // Get default background color const auto defaultBackgroundColor = context.env->getDefaultBackgroundColor(context.zoom); if (pDestinationArea) { // If destination area is specified, fill only it with background SkPaint bgPaint; bgPaint.setColor(defaultBackgroundColor.toSkColor()); bgPaint.setStyle(SkPaint::kFill_Style); canvas.drawRectCoords( pDestinationArea->top(), pDestinationArea->left(), pDestinationArea->right(), pDestinationArea->bottom(), bgPaint); } else { // Since destination area is not specified, erase whole canvas with specified color canvas.clear(defaultBackgroundColor.toSkColor()); } } AreaI destinationArea; if (pDestinationArea) { destinationArea = *pDestinationArea; } else { const auto targetSize = canvas.getDeviceSize(); destinationArea = AreaI(0, 0, targetSize.height(), targetSize.width()); } // Rasterize layers of map: rasterizeMapPrimitives(context, canvas, primitivisedObjects->polygons, PrimitivesType::Polygons, queryController); if (context.shadowMode != MapPresentationEnvironment::ShadowMode::NoShadow) rasterizeMapPrimitives(context, canvas, primitivisedObjects->polylines, PrimitivesType::Polylines_ShadowOnly, queryController); rasterizeMapPrimitives(context, canvas, primitivisedObjects->polylines, PrimitivesType::Polylines, queryController); if (metric) metric->elapsedTime += totalStopwatch.elapsed(); }