Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(899)

Unified Diff: third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp

Issue 2674003002: Scalable spelling/grammar markers (Closed)
Patch Set: formatting Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/GraphicsContext.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
diff --git a/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp b/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
index 1a71628f94224db6b529b0043b082f379cb5fe2d..49ebb7d73a25700614b7fe7f6e3f5b5805f058f3 100644
--- a/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
+++ b/third_party/WebKit/Source/platform/graphics/GraphicsContext.cpp
@@ -44,6 +44,8 @@
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "third_party/skia/include/core/SkRefCnt.h"
+#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,
+#include "third_party/skia/include/effects/SkGradientShader.h"
#include "third_party/skia/include/effects/SkLumaColorFilter.h"
#include "third_party/skia/include/effects/SkPictureImageFilter.h"
#include "third_party/skia/include/pathops/SkPathOps.h"
@@ -509,6 +511,93 @@ void GraphicsContext::drawLine(const IntPoint& point1, const IntPoint& point2) {
m_canvas->drawLine(p1.x(), p1.y(), p2.x(), p2.y(), paint);
}
+namespace {
+
+#if !OS(MACOSX)
+
+sk_sp<SkPicture> recordMarker(GraphicsContext::DocumentMarkerLineStyle style) {
+ SkColor color = (style == GraphicsContext::DocumentMarkerGrammarLineStyle)
+ ? SkColorSetRGB(0xC0, 0xC0, 0xC0)
+ : SK_ColorRED;
+
+ // Record the path equivalent to this legacy pattern:
+ // X o o X o o X
+ // o X o o X o
+
+ static const float kW = 4;
+ static const float kH = 2;
+
+ // Adjust the phase such that f' == 0 is "pixel"-centered
+ // (for optimal rasterization at native rez).
+ SkPath path;
+ path.moveTo(kW * -3 / 8, kH * 3 / 4);
+ path.cubicTo(kW * -1 / 8, kH * 3 / 4,
+ kW * -1 / 8, kH * 1 / 4,
+ kW * 1 / 8, kH * 1 / 4);
+ path.cubicTo(kW * 3 / 8, kH * 1 / 4,
+ kW * 3 / 8, kH * 3 / 4,
+ kW * 5 / 8, kH * 3 / 4);
+ path.cubicTo(kW * 7 / 8, kH * 3 / 4,
+ kW * 7 / 8, kH * 1 / 4,
+ kW * 9 / 8, kH * 1 / 4);
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(color);
+ paint.setStyle(SkPaint::kStroke_Style);
+ paint.setStrokeWidth(kH * 1 / 2);
+
+ SkPictureRecorder recorder;
+ recorder.beginRecording(kW, kH);
+ recorder.getRecordingCanvas()->drawPath(path, paint);
+
+ return recorder.finishRecordingAsPicture();
+}
+
+#else // OS(MACOSX)
+
+sk_sp<SkPicture> recordMarker(GraphicsContext::DocumentMarkerLineStyle style) {
+ SkColor color = (style == GraphicsContext::DocumentMarkerGrammarLineStyle)
+ ? SkColorSetRGB(0x6B, 0x6B, 0x6B)
+ : SkColorSetRGB(0xFB, 0x2D, 0x1D);
+
+ // Match the artwork used by the Mac.
+ static const float kW = 4;
+ static const float kH = 3;
+ static const float kR = 1.5f;
+
+ // top->bottom translucent gradient.
+ const SkColor colors[2] = {
+ SkColorSetARGB(0x48,
+ SkColorGetR(color),
+ SkColorGetG(color),
+ SkColorGetB(color)),
+ color
+ };
+ const SkPoint pts[2] = {
+ SkPoint::Make(0, 0),
+ SkPoint::Make(0, 2 * kR)
+ };
+
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(color);
+ paint.setShader(SkGradientShader::MakeLinear(pts,
+ colors,
+ nullptr,
+ ARRAY_SIZE(colors),
+ SkShader::kClamp_TileMode));
+ SkPictureRecorder recorder;
+ recorder.beginRecording(kW, kH);
+ recorder.getRecordingCanvas()->drawCircle(kR, kR, kR, paint);
+
+ return recorder.finishRecordingAsPicture();
+}
+
+#endif // OS(MACOSX)
+
+} // anonymous ns
+
void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt,
float width,
DocumentMarkerLineStyle style,
@@ -516,133 +605,44 @@ void GraphicsContext::drawLineForDocumentMarker(const FloatPoint& pt,
if (contextDisabled())
return;
- // Use 2x resources for a device scale factor of 1.5 or above.
- // This modifes the bitmaps used for the marker, not the overall
- // scaling of the marker.
- int deviceScaleFactor = m_deviceScaleFactor * zoom > 1.5f ? 2 : 1;
-
- // Create the pattern we'll use to draw the underline.
- int index = style == DocumentMarkerGrammarLineStyle ? 1 : 0;
- static SkBitmap* misspellBitmap1x[2] = {0, 0};
- static SkBitmap* misspellBitmap2x[2] = {0, 0};
- SkBitmap** misspellBitmap =
- deviceScaleFactor == 2 ? misspellBitmap2x : misspellBitmap1x;
- if (!misspellBitmap[index]) {
-#if OS(MACOSX)
- // Match the artwork used by the Mac.
- const int rowPixels = 4 * deviceScaleFactor;
- const int colPixels = 3 * deviceScaleFactor;
- SkBitmap bitmap;
- if (!bitmap.tryAllocN32Pixels(rowPixels, colPixels))
- return;
-
- bitmap.eraseARGB(0, 0, 0, 0);
- const uint32_t transparentColor = 0x00000000;
-
- if (deviceScaleFactor == 1) {
- const uint32_t colors[2][6] = {{0x2a2a0600, 0x57571000, 0xa8a81b00,
- 0xbfbf1f00, 0x70701200, 0xe0e02400},
- {0x2a0f0f0f, 0x571e1e1e, 0xa83d3d3d,
- 0xbf454545, 0x70282828, 0xe0515151}};
-
- // Pattern: a b a a b a
- // c d c c d c
- // e f e e f e
- for (int x = 0; x < colPixels; ++x) {
- uint32_t* row = bitmap.getAddr32(0, x);
- row[0] = colors[index][x * 2];
- row[1] = colors[index][x * 2 + 1];
- row[2] = colors[index][x * 2];
- row[3] = transparentColor;
- }
- } else if (deviceScaleFactor == 2) {
- const uint32_t colors[2][18] = {
- {0x0a090101, 0x33320806, 0x55540f0a, 0x37360906, 0x6e6c120c,
- 0x6e6c120c, 0x7674140d, 0x8d8b1810, 0x8d8b1810, 0x96941a11,
- 0xb3b01f15, 0xb3b01f15, 0x6d6b130c, 0xd9d62619, 0xd9d62619,
- 0x19180402, 0x7c7a150e, 0xcecb2418},
- {0x0a020202, 0x33141414, 0x55232323, 0x37161616, 0x6e2e2e2e,
- 0x6e2e2e2e, 0x76313131, 0x8d3a3a3a, 0x8d3a3a3a, 0x963e3e3e,
- 0xb34b4b4b, 0xb34b4b4b, 0x6d2d2d2d, 0xd95b5b5b, 0xd95b5b5b,
- 0x19090909, 0x7c343434, 0xce575757}};
-
- // Pattern: a b c c b a
- // d e f f e d
- // g h j j h g
- // k l m m l k
- // n o p p o n
- // q r s s r q
- for (int x = 0; x < colPixels; ++x) {
- uint32_t* row = bitmap.getAddr32(0, x);
- row[0] = colors[index][x * 3];
- row[1] = colors[index][x * 3 + 1];
- row[2] = colors[index][x * 3 + 2];
- row[3] = colors[index][x * 3 + 2];
- row[4] = colors[index][x * 3 + 1];
- row[5] = colors[index][x * 3];
- row[6] = transparentColor;
- row[7] = transparentColor;
- }
- } else
- ASSERT_NOT_REACHED();
-
- misspellBitmap[index] = new SkBitmap(bitmap);
-#else
- // We use a 2-pixel-high misspelling indicator because that seems to be
- // what Blink is designed for, and how much room there is in a typical
- // page for it.
- const int rowPixels =
- 32 * deviceScaleFactor; // Must be multiple of 4 for pattern below.
- const int colPixels = 2 * deviceScaleFactor;
- SkBitmap bitmap;
- if (!bitmap.tryAllocN32Pixels(rowPixels, colPixels))
- return;
-
- bitmap.eraseARGB(0, 0, 0, 0);
- if (deviceScaleFactor == 1)
- draw1xMarker(&bitmap, index);
- else if (deviceScaleFactor == 2)
- draw2xMarker(&bitmap, index);
- else
- ASSERT_NOT_REACHED();
-
- misspellBitmap[index] = new SkBitmap(bitmap);
-#endif
- }
+ DEFINE_STATIC_LOCAL(SkPicture*, spellingMarker,
+ (recordMarker(DocumentMarkerSpellingLineStyle).release()));
+ DEFINE_STATIC_LOCAL(SkPicture*, grammarMarker,
+ (recordMarker(DocumentMarkerGrammarLineStyle).release()));
+ const auto& marker = style == DocumentMarkerSpellingLineStyle
+ ? spellingMarker
+ : grammarMarker;
-#if OS(MACOSX)
// Position already includes zoom and device scale factor.
SkScalar originX = WebCoreFloatToSkScalar(pt.x());
SkScalar originY = WebCoreFloatToSkScalar(pt.y());
+#if OS(MACOSX)
// Make sure to draw only complete dots, and finish inside the marked text.
- float rowPixels = misspellBitmap[index]->width() * zoom / deviceScaleFactor;
- float dotCount = floorf(width / rowPixels);
- width = dotCount * rowPixels;
+ width -= fmodf(width, marker->cullRect().width() * zoom);
#else
- SkScalar originX = WebCoreFloatToSkScalar(pt.x());
-
// Offset it vertically by 1 so that there's some space under the text.
- SkScalar originY = WebCoreFloatToSkScalar(pt.y()) + 1;
+ originY += 1;
#endif
- SkMatrix localMatrix;
- localMatrix.setScale(zoom / deviceScaleFactor, zoom / deviceScaleFactor);
- localMatrix.postTranslate(originX, originY);
+ const auto rect = SkRect::MakeWH(width, marker->cullRect().height() * zoom);
+ const auto localMatrix = SkMatrix::MakeScale(zoom, zoom);
PaintFlags paint;
- paint.setShader(WrapSkShader(SkShader::MakeBitmapShader(
- *misspellBitmap[index], SkShader::kRepeat_TileMode,
- SkShader::kRepeat_TileMode, &localMatrix)));
-
- SkRect rect;
- rect.set(
- originX, originY, originX + WebCoreFloatToSkScalar(width),
- originY +
- SkIntToScalar(misspellBitmap[index]->height() / deviceScaleFactor) *
- zoom);
-
- drawRect(rect, paint);
+ paint.setAntiAlias(true);
+ paint.setShader(WrapSkShader(
+ SkShader::MakePictureShader(sk_ref_sp(marker),
+ SkShader::kRepeat_TileMode,
+ SkShader::kClamp_TileMode,
+ &localMatrix,
+ nullptr)));
+
+ // Apply the origin translation as a global transform. This ensures that the
+ // shader local matrix depends solely on zoom => Skia can reuse the same
+ // cached tile for all markers at a given zoom level.
+ SkAutoCanvasRestore acr(m_canvas, true);
+ m_canvas->translate(originX, originY);
+ m_canvas->drawRect(rect, paint);
}
void GraphicsContext::drawLineForText(const FloatPoint& pt, float width) {
@@ -1330,95 +1330,4 @@ sk_sp<SkColorFilter> GraphicsContext::WebCoreColorFilterToSkiaColorFilter(
return nullptr;
}
-#if !OS(MACOSX)
-void GraphicsContext::draw2xMarker(SkBitmap* bitmap, int index) {
- const SkPMColor lineColor = lineColors(index);
- const SkPMColor antiColor1 = antiColors1(index);
- const SkPMColor antiColor2 = antiColors2(index);
-
- uint32_t* row1 = bitmap->getAddr32(0, 0);
- uint32_t* row2 = bitmap->getAddr32(0, 1);
- uint32_t* row3 = bitmap->getAddr32(0, 2);
- uint32_t* row4 = bitmap->getAddr32(0, 3);
-
- // Pattern: X0o o0X0o o0
- // XX0o o0XXX0o o0X
- // o0XXX0o o0XXX0o
- // o0X0o o0X0o
- const SkPMColor row1Color[] = {lineColor, antiColor1, antiColor2, 0,
- 0, 0, antiColor2, antiColor1};
- const SkPMColor row2Color[] = {lineColor, lineColor, antiColor1, antiColor2,
- 0, antiColor2, antiColor1, lineColor};
- const SkPMColor row3Color[] = {0, antiColor2, antiColor1, lineColor,
- lineColor, lineColor, antiColor1, antiColor2};
- const SkPMColor row4Color[] = {0, 0, antiColor2, antiColor1,
- lineColor, antiColor1, antiColor2, 0};
-
- for (int x = 0; x < bitmap->width() + 8; x += 8) {
- int count = std::min(bitmap->width() - x, 8);
- if (count > 0) {
- memcpy(row1 + x, row1Color, count * sizeof(SkPMColor));
- memcpy(row2 + x, row2Color, count * sizeof(SkPMColor));
- memcpy(row3 + x, row3Color, count * sizeof(SkPMColor));
- memcpy(row4 + x, row4Color, count * sizeof(SkPMColor));
- }
- }
-}
-
-void GraphicsContext::draw1xMarker(SkBitmap* bitmap, int index) {
- const uint32_t lineColor = lineColors(index);
- const uint32_t antiColor = antiColors2(index);
-
- // Pattern: X o o X o o X
- // o X o o X o
- uint32_t* row1 = bitmap->getAddr32(0, 0);
- uint32_t* row2 = bitmap->getAddr32(0, 1);
- for (int x = 0; x < bitmap->width(); x++) {
- switch (x % 4) {
- case 0:
- row1[x] = lineColor;
- break;
- case 1:
- row1[x] = antiColor;
- row2[x] = antiColor;
- break;
- case 2:
- row2[x] = lineColor;
- break;
- case 3:
- row1[x] = antiColor;
- row2[x] = antiColor;
- break;
- }
- }
-}
-
-SkPMColor GraphicsContext::lineColors(int index) {
- static const SkPMColor colors[] = {
- SkPreMultiplyARGB(0xFF, 0xFF, 0x00, 0x00), // Opaque red.
- SkPreMultiplyARGB(0xFF, 0xC0, 0xC0, 0xC0) // Opaque gray.
- };
-
- return colors[index];
-}
-
-SkPMColor GraphicsContext::antiColors1(int index) {
- static const SkPMColor colors[] = {
- SkPreMultiplyARGB(0xB0, 0xFF, 0x00, 0x00), // Semitransparent red.
- SkPreMultiplyARGB(0xB0, 0xC0, 0xC0, 0xC0) // Semitransparent gray.
- };
-
- return colors[index];
-}
-
-SkPMColor GraphicsContext::antiColors2(int index) {
- static const SkPMColor colors[] = {
- SkPreMultiplyARGB(0x60, 0xFF, 0x00, 0x00), // More transparent red
- SkPreMultiplyARGB(0x60, 0xC0, 0xC0, 0xC0) // More transparent gray
- };
-
- return colors[index];
-}
-#endif
-
} // namespace blink
« no previous file with comments | « third_party/WebKit/Source/platform/graphics/GraphicsContext.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698