OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. | 2 * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved. |
3 * Copyright (C) 2013 Google Inc. All rights reserved. | 3 * Copyright (C) 2013 Google Inc. All rights reserved. |
4 * | 4 * |
5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
6 * modification, are permitted provided that the following conditions | 6 * modification, are permitted provided that the following conditions |
7 * are met: | 7 * are met: |
8 * 1. Redistributions of source code must retain the above copyright | 8 * 1. Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * 2. Redistributions in binary form must reproduce the above copyright | 10 * 2. Redistributions in binary form must reproduce the above copyright |
(...skipping 26 matching lines...) Expand all Loading... | |
37 #include "platform/graphics/paint/PaintRecord.h" | 37 #include "platform/graphics/paint/PaintRecord.h" |
38 #include "platform/graphics/paint/PaintRecorder.h" | 38 #include "platform/graphics/paint/PaintRecorder.h" |
39 #include "platform/instrumentation/tracing/TraceEvent.h" | 39 #include "platform/instrumentation/tracing/TraceEvent.h" |
40 #include "platform/weborigin/KURL.h" | 40 #include "platform/weborigin/KURL.h" |
41 #include "skia/ext/platform_canvas.h" | 41 #include "skia/ext/platform_canvas.h" |
42 #include "third_party/skia/include/core/SkAnnotation.h" | 42 #include "third_party/skia/include/core/SkAnnotation.h" |
43 #include "third_party/skia/include/core/SkColorFilter.h" | 43 #include "third_party/skia/include/core/SkColorFilter.h" |
44 #include "third_party/skia/include/core/SkData.h" | 44 #include "third_party/skia/include/core/SkData.h" |
45 #include "third_party/skia/include/core/SkRRect.h" | 45 #include "third_party/skia/include/core/SkRRect.h" |
46 #include "third_party/skia/include/core/SkRefCnt.h" | 46 #include "third_party/skia/include/core/SkRefCnt.h" |
47 #include "third_party/skia/include/core/SkUnPreMultiply.h" | |
Stephen White
2017/03/02 15:06:26
uNit: is this still used anywhere? Maybe it could
f(malita)
2017/03/03 19:16:09
Hmm, nope, how did it sneak in there? :)
Thanks,
| |
48 #include "third_party/skia/include/effects/SkGradientShader.h" | |
47 #include "third_party/skia/include/effects/SkLumaColorFilter.h" | 49 #include "third_party/skia/include/effects/SkLumaColorFilter.h" |
48 #include "third_party/skia/include/effects/SkPictureImageFilter.h" | 50 #include "third_party/skia/include/effects/SkPictureImageFilter.h" |
49 #include "third_party/skia/include/pathops/SkPathOps.h" | 51 #include "third_party/skia/include/pathops/SkPathOps.h" |
50 #include "third_party/skia/include/utils/SkNullCanvas.h" | 52 #include "third_party/skia/include/utils/SkNullCanvas.h" |
51 #include "wtf/Assertions.h" | 53 #include "wtf/Assertions.h" |
52 #include "wtf/MathExtras.h" | 54 #include "wtf/MathExtras.h" |
53 #include <memory> | 55 #include <memory> |
54 | 56 |
55 namespace blink { | 57 namespace blink { |
56 | 58 |
(...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
502 PaintFlags fillPaint; | 504 PaintFlags fillPaint; |
503 fillPaint.setColor(paint.getColor()); | 505 fillPaint.setColor(paint.getColor()); |
504 drawRect(r1, fillPaint); | 506 drawRect(r1, fillPaint); |
505 drawRect(r2, fillPaint); | 507 drawRect(r2, fillPaint); |
506 } | 508 } |
507 | 509 |
508 adjustLineToPixelBoundaries(p1, p2, width, penStyle); | 510 adjustLineToPixelBoundaries(p1, p2, width, penStyle); |
509 m_canvas->drawLine(p1.x(), p1.y(), p2.x(), p2.y(), paint); | 511 m_canvas->drawLine(p1.x(), p1.y(), p2.x(), p2.y(), paint); |
510 } | 512 } |
511 | 513 |
514 namespace { | |
515 | |
516 #if !OS(MACOSX) | |
517 | |
518 sk_sp<SkPicture> recordMarker(GraphicsContext::DocumentMarkerLineStyle style) { | |
519 SkColor color = (style == GraphicsContext::DocumentMarkerGrammarLineStyle) | |
520 ? SkColorSetRGB(0xC0, 0xC0, 0xC0) | |
521 : SK_ColorRED; | |
522 | |
523 // Record the path equivalent to this legacy pattern: | |
524 // X o o X o o X | |
525 // o X o o X o | |
526 | |
527 static const float kW = 4; | |
528 static const float kH = 2; | |
529 | |
530 // Adjust the phase such that f' == 0 is "pixel"-centered | |
531 // (for optimal rasterization at native rez). | |
532 SkPath path; | |
533 path.moveTo(kW * -3 / 8, kH * 3 / 4); | |
534 path.cubicTo(kW * -1 / 8, kH * 3 / 4, | |
535 kW * -1 / 8, kH * 1 / 4, | |
536 kW * 1 / 8, kH * 1 / 4); | |
537 path.cubicTo(kW * 3 / 8, kH * 1 / 4, | |
538 kW * 3 / 8, kH * 3 / 4, | |
539 kW * 5 / 8, kH * 3 / 4); | |
540 path.cubicTo(kW * 7 / 8, kH * 3 / 4, | |
541 kW * 7 / 8, kH * 1 / 4, | |
542 kW * 9 / 8, kH * 1 / 4); | |
543 | |
544 SkPaint paint; | |
545 paint.setAntiAlias(true); | |
546 paint.setColor(color); | |
547 paint.setStyle(SkPaint::kStroke_Style); | |
548 paint.setStrokeWidth(kH * 1 / 2); | |
549 | |
550 SkPictureRecorder recorder; | |
551 recorder.beginRecording(kW, kH); | |
552 recorder.getRecordingCanvas()->drawPath(path, paint); | |
553 | |
554 return recorder.finishRecordingAsPicture(); | |
555 } | |
556 | |
557 #else // OS(MACOSX) | |
558 | |
559 sk_sp<SkPicture> recordMarker(GraphicsContext::DocumentMarkerLineStyle style) { | |
560 SkColor color = (style == GraphicsContext::DocumentMarkerGrammarLineStyle) | |
561 ? SkColorSetRGB(0x6B, 0x6B, 0x6B) | |
562 : SkColorSetRGB(0xFB, 0x2D, 0x1D); | |
563 | |
564 // Match the artwork used by the Mac. | |
565 static const float kW = 4; | |
566 static const float kH = 3; | |
567 static const float kR = 1.5f; | |
568 | |
569 // top->bottom translucent gradient. | |
570 const SkColor colors[2] = { | |
571 SkColorSetARGB(0x48, | |
572 SkColorGetR(color), | |
573 SkColorGetG(color), | |
574 SkColorGetB(color)), | |
575 color | |
576 }; | |
577 const SkPoint pts[2] = { | |
578 SkPoint::Make(0, 0), | |
579 SkPoint::Make(0, 2 * kR) | |
580 }; | |
581 | |
582 SkPaint paint; | |
583 paint.setAntiAlias(true); | |
584 paint.setColor(color); | |
585 paint.setShader(SkGradientShader::MakeLinear(pts, | |
586 colors, | |
587 nullptr, | |
588 ARRAY_SIZE(colors), | |
589 SkShader::kClamp_TileMode)); | |
590 SkPictureRecorder recorder; | |
591 recorder.beginRecording(kW, kH); | |
592 recorder.getRecordingCanvas()->drawCircle(kR, kR, kR, paint); | |
593 | |
594 return recorder.finishRecordingAsPicture(); | |
595 } | |
596 | |
597 #endif // OS(MACOSX) | |
598 | |
599 } // anonymous ns | |
600 | |
512 void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, | 601 void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt, |
513 float width, | 602 float width, |
514 DocumentMarkerLineStyle style, | 603 DocumentMarkerLineStyle style, |
515 float zoom) { | 604 float zoom) { |
516 if (contextDisabled()) | 605 if (contextDisabled()) |
517 return; | 606 return; |
518 | 607 |
519 // Use 2x resources for a device scale factor of 1.5 or above. | 608 DEFINE_STATIC_LOCAL(SkPicture*, spellingMarker, |
520 // This modifes the bitmaps used for the marker, not the overall | 609 (recordMarker(DocumentMarkerSpellingLineStyle).release())) ; |
521 // scaling of the marker. | 610 DEFINE_STATIC_LOCAL(SkPicture*, grammarMarker, |
522 int deviceScaleFactor = m_deviceScaleFactor * zoom > 1.5f ? 2 : 1; | 611 (recordMarker(DocumentMarkerGrammarLineStyle).release())); |
612 const auto& marker = style == DocumentMarkerSpellingLineStyle | |
613 ? spellingMarker | |
614 : grammarMarker; | |
523 | 615 |
524 // Create the pattern we'll use to draw the underline. | |
525 int index = style == DocumentMarkerGrammarLineStyle ? 1 : 0; | |
526 static SkBitmap* misspellBitmap1x[2] = {0, 0}; | |
527 static SkBitmap* misspellBitmap2x[2] = {0, 0}; | |
528 SkBitmap** misspellBitmap = | |
529 deviceScaleFactor == 2 ? misspellBitmap2x : misspellBitmap1x; | |
530 if (!misspellBitmap[index]) { | |
531 #if OS(MACOSX) | |
532 // Match the artwork used by the Mac. | |
533 const int rowPixels = 4 * deviceScaleFactor; | |
534 const int colPixels = 3 * deviceScaleFactor; | |
535 SkBitmap bitmap; | |
536 if (!bitmap.tryAllocN32Pixels(rowPixels, colPixels)) | |
537 return; | |
538 | |
539 bitmap.eraseARGB(0, 0, 0, 0); | |
540 const uint32_t transparentColor = 0x00000000; | |
541 | |
542 if (deviceScaleFactor == 1) { | |
543 const uint32_t colors[2][6] = {{0x2a2a0600, 0x57571000, 0xa8a81b00, | |
544 0xbfbf1f00, 0x70701200, 0xe0e02400}, | |
545 {0x2a0f0f0f, 0x571e1e1e, 0xa83d3d3d, | |
546 0xbf454545, 0x70282828, 0xe0515151}}; | |
547 | |
548 // Pattern: a b a a b a | |
549 // c d c c d c | |
550 // e f e e f e | |
551 for (int x = 0; x < colPixels; ++x) { | |
552 uint32_t* row = bitmap.getAddr32(0, x); | |
553 row[0] = colors[index][x * 2]; | |
554 row[1] = colors[index][x * 2 + 1]; | |
555 row[2] = colors[index][x * 2]; | |
556 row[3] = transparentColor; | |
557 } | |
558 } else if (deviceScaleFactor == 2) { | |
559 const uint32_t colors[2][18] = { | |
560 {0x0a090101, 0x33320806, 0x55540f0a, 0x37360906, 0x6e6c120c, | |
561 0x6e6c120c, 0x7674140d, 0x8d8b1810, 0x8d8b1810, 0x96941a11, | |
562 0xb3b01f15, 0xb3b01f15, 0x6d6b130c, 0xd9d62619, 0xd9d62619, | |
563 0x19180402, 0x7c7a150e, 0xcecb2418}, | |
564 {0x0a020202, 0x33141414, 0x55232323, 0x37161616, 0x6e2e2e2e, | |
565 0x6e2e2e2e, 0x76313131, 0x8d3a3a3a, 0x8d3a3a3a, 0x963e3e3e, | |
566 0xb34b4b4b, 0xb34b4b4b, 0x6d2d2d2d, 0xd95b5b5b, 0xd95b5b5b, | |
567 0x19090909, 0x7c343434, 0xce575757}}; | |
568 | |
569 // Pattern: a b c c b a | |
570 // d e f f e d | |
571 // g h j j h g | |
572 // k l m m l k | |
573 // n o p p o n | |
574 // q r s s r q | |
575 for (int x = 0; x < colPixels; ++x) { | |
576 uint32_t* row = bitmap.getAddr32(0, x); | |
577 row[0] = colors[index][x * 3]; | |
578 row[1] = colors[index][x * 3 + 1]; | |
579 row[2] = colors[index][x * 3 + 2]; | |
580 row[3] = colors[index][x * 3 + 2]; | |
581 row[4] = colors[index][x * 3 + 1]; | |
582 row[5] = colors[index][x * 3]; | |
583 row[6] = transparentColor; | |
584 row[7] = transparentColor; | |
585 } | |
586 } else | |
587 ASSERT_NOT_REACHED(); | |
588 | |
589 misspellBitmap[index] = new SkBitmap(bitmap); | |
590 #else | |
591 // We use a 2-pixel-high misspelling indicator because that seems to be | |
592 // what Blink is designed for, and how much room there is in a typical | |
593 // page for it. | |
594 const int rowPixels = | |
595 32 * deviceScaleFactor; // Must be multiple of 4 for pattern below. | |
596 const int colPixels = 2 * deviceScaleFactor; | |
597 SkBitmap bitmap; | |
598 if (!bitmap.tryAllocN32Pixels(rowPixels, colPixels)) | |
599 return; | |
600 | |
601 bitmap.eraseARGB(0, 0, 0, 0); | |
602 if (deviceScaleFactor == 1) | |
603 draw1xMarker(&bitmap, index); | |
604 else if (deviceScaleFactor == 2) | |
605 draw2xMarker(&bitmap, index); | |
606 else | |
607 ASSERT_NOT_REACHED(); | |
608 | |
609 misspellBitmap[index] = new SkBitmap(bitmap); | |
610 #endif | |
611 } | |
612 | |
613 #if OS(MACOSX) | |
614 // Position already includes zoom and device scale factor. | 616 // Position already includes zoom and device scale factor. |
615 SkScalar originX = WebCoreFloatToSkScalar(pt.x()); | 617 SkScalar originX = WebCoreFloatToSkScalar(pt.x()); |
616 SkScalar originY = WebCoreFloatToSkScalar(pt.y()); | 618 SkScalar originY = WebCoreFloatToSkScalar(pt.y()); |
617 | 619 |
620 #if OS(MACOSX) | |
618 // Make sure to draw only complete dots, and finish inside the marked text. | 621 // Make sure to draw only complete dots, and finish inside the marked text. |
619 float rowPixels = misspellBitmap[index]->width() * zoom / deviceScaleFactor; | 622 width -= fmodf(width, marker->cullRect().width() * zoom); |
620 float dotCount = floorf(width / rowPixels); | |
621 width = dotCount * rowPixels; | |
622 #else | 623 #else |
623 SkScalar originX = WebCoreFloatToSkScalar(pt.x()); | |
624 | |
625 // Offset it vertically by 1 so that there's some space under the text. | 624 // Offset it vertically by 1 so that there's some space under the text. |
626 SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1; | 625 originY += 1; |
627 #endif | 626 #endif |
628 | 627 |
629 SkMatrix localMatrix; | 628 const auto rect = SkRect::MakeWH(width, marker->cullRect().height() * zoom); |
630 localMatrix.setScale(zoom / deviceScaleFactor, zoom / deviceScaleFactor); | 629 const auto localMatrix = SkMatrix::MakeScale(zoom, zoom); |
631 localMatrix.postTranslate(originX, originY); | |
632 | 630 |
633 PaintFlags paint; | 631 PaintFlags paint; |
634 paint.setShader(WrapSkShader(SkShader::MakeBitmapShader( | 632 paint.setAntiAlias(true); |
635 *misspellBitmap[index], SkShader::kRepeat_TileMode, | 633 paint.setShader(WrapSkShader( |
636 SkShader::kRepeat_TileMode, &localMatrix))); | 634 SkShader::MakePictureShader(sk_ref_sp(marker), |
635 SkShader::kRepeat_TileMode, | |
636 SkShader::kClamp_TileMode, | |
637 &localMatrix, | |
638 nullptr))); | |
637 | 639 |
638 SkRect rect; | 640 // Apply the origin translation as a global transform. This ensures that the |
639 rect.set( | 641 // shader local matrix depends solely on zoom => Skia can reuse the same |
640 originX, originY, originX + WebCoreFloatToSkScalar(width), | 642 // cached tile for all markers at a given zoom level. |
641 originY + | 643 SkAutoCanvasRestore acr(m_canvas, true); |
642 SkIntToScalar(misspellBitmap[index]->height() / deviceScaleFactor) * | 644 m_canvas->translate(originX, originY); |
643 zoom); | 645 m_canvas->drawRect(rect, paint); |
644 | |
645 drawRect(rect, paint); | |
646 } | 646 } |
647 | 647 |
648 void GraphicsContext::drawLineForText(const FloatPoint& pt, float width) { | 648 void GraphicsContext::drawLineForText(const FloatPoint& pt, float width) { |
649 if (contextDisabled()) | 649 if (contextDisabled()) |
650 return; | 650 return; |
651 | 651 |
652 if (width <= 0) | 652 if (width <= 0) |
653 return; | 653 return; |
654 | 654 |
655 PaintFlags paint; | 655 PaintFlags paint; |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1323 case ColorFilterNone: | 1323 case ColorFilterNone: |
1324 break; | 1324 break; |
1325 default: | 1325 default: |
1326 ASSERT_NOT_REACHED(); | 1326 ASSERT_NOT_REACHED(); |
1327 break; | 1327 break; |
1328 } | 1328 } |
1329 | 1329 |
1330 return nullptr; | 1330 return nullptr; |
1331 } | 1331 } |
1332 | 1332 |
1333 #if !OS(MACOSX) | |
1334 void GraphicsContext::draw2xMarker(SkBitmap* bitmap, int index) { | |
1335 const SkPMColor lineColor = lineColors(index); | |
1336 const SkPMColor antiColor1 = antiColors1(index); | |
1337 const SkPMColor antiColor2 = antiColors2(index); | |
1338 | |
1339 uint32_t* row1 = bitmap->getAddr32(0, 0); | |
1340 uint32_t* row2 = bitmap->getAddr32(0, 1); | |
1341 uint32_t* row3 = bitmap->getAddr32(0, 2); | |
1342 uint32_t* row4 = bitmap->getAddr32(0, 3); | |
1343 | |
1344 // Pattern: X0o o0X0o o0 | |
1345 // XX0o o0XXX0o o0X | |
1346 // o0XXX0o o0XXX0o | |
1347 // o0X0o o0X0o | |
1348 const SkPMColor row1Color[] = {lineColor, antiColor1, antiColor2, 0, | |
1349 0, 0, antiColor2, antiColor1}; | |
1350 const SkPMColor row2Color[] = {lineColor, lineColor, antiColor1, antiColor2, | |
1351 0, antiColor2, antiColor1, lineColor}; | |
1352 const SkPMColor row3Color[] = {0, antiColor2, antiColor1, lineColor, | |
1353 lineColor, lineColor, antiColor1, antiColor2}; | |
1354 const SkPMColor row4Color[] = {0, 0, antiColor2, antiColor1, | |
1355 lineColor, antiColor1, antiColor2, 0}; | |
1356 | |
1357 for (int x = 0; x < bitmap->width() + 8; x += 8) { | |
1358 int count = std::min(bitmap->width() - x, 8); | |
1359 if (count > 0) { | |
1360 memcpy(row1 + x, row1Color, count * sizeof(SkPMColor)); | |
1361 memcpy(row2 + x, row2Color, count * sizeof(SkPMColor)); | |
1362 memcpy(row3 + x, row3Color, count * sizeof(SkPMColor)); | |
1363 memcpy(row4 + x, row4Color, count * sizeof(SkPMColor)); | |
1364 } | |
1365 } | |
1366 } | |
1367 | |
1368 void GraphicsContext::draw1xMarker(SkBitmap* bitmap, int index) { | |
1369 const uint32_t lineColor = lineColors(index); | |
1370 const uint32_t antiColor = antiColors2(index); | |
1371 | |
1372 // Pattern: X o o X o o X | |
1373 // o X o o X o | |
1374 uint32_t* row1 = bitmap->getAddr32(0, 0); | |
1375 uint32_t* row2 = bitmap->getAddr32(0, 1); | |
1376 for (int x = 0; x < bitmap->width(); x++) { | |
1377 switch (x % 4) { | |
1378 case 0: | |
1379 row1[x] = lineColor; | |
1380 break; | |
1381 case 1: | |
1382 row1[x] = antiColor; | |
1383 row2[x] = antiColor; | |
1384 break; | |
1385 case 2: | |
1386 row2[x] = lineColor; | |
1387 break; | |
1388 case 3: | |
1389 row1[x] = antiColor; | |
1390 row2[x] = antiColor; | |
1391 break; | |
1392 } | |
1393 } | |
1394 } | |
1395 | |
1396 SkPMColor GraphicsContext::lineColors(int index) { | |
1397 static const SkPMColor colors[] = { | |
1398 SkPreMultiplyARGB(0xFF, 0xFF, 0x00, 0x00), // Opaque red. | |
1399 SkPreMultiplyARGB(0xFF, 0xC0, 0xC0, 0xC0) // Opaque gray. | |
1400 }; | |
1401 | |
1402 return colors[index]; | |
1403 } | |
1404 | |
1405 SkPMColor GraphicsContext::antiColors1(int index) { | |
1406 static const SkPMColor colors[] = { | |
1407 SkPreMultiplyARGB(0xB0, 0xFF, 0x00, 0x00), // Semitransparent red. | |
1408 SkPreMultiplyARGB(0xB0, 0xC0, 0xC0, 0xC0) // Semitransparent gray. | |
1409 }; | |
1410 | |
1411 return colors[index]; | |
1412 } | |
1413 | |
1414 SkPMColor GraphicsContext::antiColors2(int index) { | |
1415 static const SkPMColor colors[] = { | |
1416 SkPreMultiplyARGB(0x60, 0xFF, 0x00, 0x00), // More transparent red | |
1417 SkPreMultiplyARGB(0x60, 0xC0, 0xC0, 0xC0) // More transparent gray | |
1418 }; | |
1419 | |
1420 return colors[index]; | |
1421 } | |
1422 #endif | |
1423 | |
1424 } // namespace blink | 1333 } // namespace blink |
OLD | NEW |