OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gfx/render_text.h" | 5 #include "ui/gfx/render_text.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <climits> | 8 #include <climits> |
9 | 9 |
10 #include "base/command_line.h" | |
10 #include "base/i18n/break_iterator.h" | 11 #include "base/i18n/break_iterator.h" |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
12 #include "base/stl_util.h" | 13 #include "base/stl_util.h" |
13 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
14 #include "third_party/icu/source/common/unicode/rbbi.h" | 15 #include "third_party/icu/source/common/unicode/rbbi.h" |
15 #include "third_party/icu/source/common/unicode/utf16.h" | 16 #include "third_party/icu/source/common/unicode/utf16.h" |
16 #include "third_party/skia/include/core/SkTypeface.h" | 17 #include "third_party/skia/include/core/SkTypeface.h" |
17 #include "third_party/skia/include/effects/SkGradientShader.h" | 18 #include "third_party/skia/include/effects/SkGradientShader.h" |
18 #include "ui/gfx/canvas.h" | 19 #include "ui/gfx/canvas.h" |
19 #include "ui/gfx/insets.h" | 20 #include "ui/gfx/insets.h" |
21 #include "ui/gfx/render_text_harfbuzz.h" | |
22 #include "ui/gfx/scoped_canvas.h" | |
20 #include "ui/gfx/skia_util.h" | 23 #include "ui/gfx/skia_util.h" |
24 #include "ui/gfx/switches.h" | |
21 #include "ui/gfx/text_constants.h" | 25 #include "ui/gfx/text_constants.h" |
22 #include "ui/gfx/text_elider.h" | 26 #include "ui/gfx/text_elider.h" |
23 #include "ui/gfx/text_utils.h" | 27 #include "ui/gfx/text_utils.h" |
24 #include "ui/gfx/utf16_indexing.h" | 28 #include "ui/gfx/utf16_indexing.h" |
25 | 29 |
26 namespace gfx { | 30 namespace gfx { |
27 | 31 |
28 namespace { | 32 namespace { |
29 | 33 |
30 // All chars are replaced by this char when the password style is set. | 34 // All chars are replaced by this char when the password style is set. |
(...skipping 180 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
211 } | 215 } |
212 | 216 |
213 void SkiaTextRenderer::SetTextSize(SkScalar size) { | 217 void SkiaTextRenderer::SetTextSize(SkScalar size) { |
214 paint_.setTextSize(size); | 218 paint_.setTextSize(size); |
215 } | 219 } |
216 | 220 |
217 void SkiaTextRenderer::SetFontFamilyWithStyle(const std::string& family, | 221 void SkiaTextRenderer::SetFontFamilyWithStyle(const std::string& family, |
218 int style) { | 222 int style) { |
219 DCHECK(!family.empty()); | 223 DCHECK(!family.empty()); |
220 | 224 |
221 SkTypeface::Style skia_style = ConvertFontStyleToSkiaTypefaceStyle(style); | 225 skia::RefPtr<SkTypeface> typeface = CreateSkiaTypeface(family.c_str(), style); |
222 skia::RefPtr<SkTypeface> typeface = | |
223 skia::AdoptRef(SkTypeface::CreateFromName(family.c_str(), skia_style)); | |
224 if (typeface) { | 226 if (typeface) { |
225 // |paint_| adds its own ref. So don't |release()| it from the ref ptr here. | 227 // |paint_| adds its own ref. So don't |release()| it from the ref ptr here. |
226 SetTypeface(typeface.get()); | 228 SetTypeface(typeface.get()); |
227 | 229 |
228 // Enable fake bold text if bold style is needed but new typeface does not | 230 // Enable fake bold text if bold style is needed but new typeface does not |
229 // have it. | 231 // have it. |
230 paint_.setFakeBoldText((skia_style & SkTypeface::kBold) && | 232 paint_.setFakeBoldText((style & gfx::Font::BOLD) && !typeface->isBold()); |
231 !typeface->isBold()); | |
232 } | 233 } |
233 } | 234 } |
234 | 235 |
235 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { | 236 void SkiaTextRenderer::SetForegroundColor(SkColor foreground) { |
236 paint_.setColor(foreground); | 237 paint_.setColor(foreground); |
237 } | 238 } |
238 | 239 |
239 void SkiaTextRenderer::SetShader(SkShader* shader, const Rect& bounds) { | 240 void SkiaTextRenderer::SetShader(SkShader* shader, const Rect& bounds) { |
240 bounds_ = RectToSkRect(bounds); | 241 bounds_ = RectToSkRect(bounds); |
241 paint_.setShader(shader); | 242 paint_.setShader(shader); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
312 const SkScalar height = SkScalarMul(text_size, kLineThickness); | 313 const SkScalar height = SkScalarMul(text_size, kLineThickness); |
313 const SkScalar offset = SkScalarMulAdd(text_size, kStrikeThroughOffset, y); | 314 const SkScalar offset = SkScalarMulAdd(text_size, kStrikeThroughOffset, y); |
314 const SkRect r = SkRect::MakeLTRB(x, offset, x + width, offset + height); | 315 const SkRect r = SkRect::MakeLTRB(x, offset, x + width, offset + height); |
315 canvas_skia_->drawRect(r, paint_); | 316 canvas_skia_->drawRect(r, paint_); |
316 } | 317 } |
317 | 318 |
318 SkiaTextRenderer::DiagonalStrike::DiagonalStrike(Canvas* canvas, | 319 SkiaTextRenderer::DiagonalStrike::DiagonalStrike(Canvas* canvas, |
319 Point start, | 320 Point start, |
320 const SkPaint& paint) | 321 const SkPaint& paint) |
321 : canvas_(canvas), | 322 : canvas_(canvas), |
323 matrix_(canvas->sk_canvas()->getTotalMatrix()), | |
322 start_(start), | 324 start_(start), |
323 paint_(paint), | 325 paint_(paint), |
324 total_length_(0) { | 326 total_length_(0) { |
325 } | 327 } |
326 | 328 |
327 SkiaTextRenderer::DiagonalStrike::~DiagonalStrike() { | 329 SkiaTextRenderer::DiagonalStrike::~DiagonalStrike() { |
328 } | 330 } |
329 | 331 |
330 void SkiaTextRenderer::DiagonalStrike::AddPiece(int length, SkColor color) { | 332 void SkiaTextRenderer::DiagonalStrike::AddPiece(int length, SkColor color) { |
331 pieces_.push_back(Piece(length, color)); | 333 pieces_.push_back(Piece(length, color)); |
332 total_length_ += length; | 334 total_length_ += length; |
333 } | 335 } |
334 | 336 |
335 void SkiaTextRenderer::DiagonalStrike::Draw() { | 337 void SkiaTextRenderer::DiagonalStrike::Draw() { |
336 const SkScalar text_size = paint_.getTextSize(); | 338 const SkScalar text_size = paint_.getTextSize(); |
337 const SkScalar offset = SkScalarMul(text_size, kDiagonalStrikeMarginOffset); | 339 const SkScalar offset = SkScalarMul(text_size, kDiagonalStrikeMarginOffset); |
338 const int thickness = | 340 const int thickness = |
339 SkScalarCeilToInt(SkScalarMul(text_size, kLineThickness) * 2); | 341 SkScalarCeilToInt(SkScalarMul(text_size, kLineThickness) * 2); |
340 const int height = SkScalarCeilToInt(text_size - offset); | 342 const int height = SkScalarCeilToInt(text_size - offset); |
341 const Point end = start_ + Vector2d(total_length_, -height); | 343 const Point end = start_ + Vector2d(total_length_, -height); |
344 const int clip_height = height + 2 * thickness; | |
342 | 345 |
343 paint_.setAntiAlias(true); | 346 paint_.setAntiAlias(true); |
344 paint_.setStrokeWidth(thickness); | 347 paint_.setStrokeWidth(thickness); |
345 | 348 |
349 ScopedCanvas scoped_canvas(canvas_); | |
350 | |
351 SkCanvas* sk_canvas = canvas_->sk_canvas(); | |
352 sk_canvas->setMatrix(matrix_); | |
353 | |
346 const bool clipped = pieces_.size() > 1; | 354 const bool clipped = pieces_.size() > 1; |
347 int x = start_.x(); | 355 int x = start_.x(); |
348 for (size_t i = 0; i < pieces_.size(); ++i) { | 356 for (size_t i = 0; i < pieces_.size(); ++i) { |
349 paint_.setColor(pieces_[i].second); | 357 paint_.setColor(pieces_[i].second); |
350 | 358 |
351 if (clipped) { | 359 if (clipped) { |
352 canvas_->Save(); | 360 sk_canvas->clipRect(RectToSkRect( |
Alexei Svitkine (slow)
2014/05/12 15:58:31
The previous code restored at every iteration, whe
ckocagil
2014/05/13 15:03:48
We're not keeping the clip here, the SkRegion::kRe
| |
353 canvas_->ClipRect(Rect(x, 0, pieces_[i].first, start_.y() + thickness)); | 361 Rect(x, end.y() - thickness, pieces_[i].first, clip_height)), |
362 SkRegion::kReplace_Op); | |
354 } | 363 } |
355 | 364 |
356 canvas_->DrawLine(start_, end, paint_); | 365 canvas_->DrawLine(start_, end, paint_); |
357 | 366 |
358 if (clipped) | |
359 canvas_->Restore(); | |
360 | |
361 x += pieces_[i].first; | 367 x += pieces_[i].first; |
362 } | 368 } |
363 } | 369 } |
364 | 370 |
365 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, | 371 StyleIterator::StyleIterator(const BreakList<SkColor>& colors, |
366 const std::vector<BreakList<bool> >& styles) | 372 const std::vector<BreakList<bool> >& styles) |
367 : colors_(colors), | 373 : colors_(colors), |
368 styles_(styles) { | 374 styles_(styles) { |
369 color_ = colors_.breaks().begin(); | 375 color_ = colors_.breaks().begin(); |
370 for (size_t i = 0; i < styles_.size(); ++i) | 376 for (size_t i = 0; i < styles_.size(); ++i) |
(...skipping 16 matching lines...) Expand all Loading... | |
387 } | 393 } |
388 | 394 |
389 LineSegment::LineSegment() : run(0) {} | 395 LineSegment::LineSegment() : run(0) {} |
390 | 396 |
391 LineSegment::~LineSegment() {} | 397 LineSegment::~LineSegment() {} |
392 | 398 |
393 Line::Line() : preceding_heights(0), baseline(0) {} | 399 Line::Line() : preceding_heights(0), baseline(0) {} |
394 | 400 |
395 Line::~Line() {} | 401 Line::~Line() {} |
396 | 402 |
403 skia::RefPtr<SkTypeface> CreateSkiaTypeface(const std::string& family, | |
404 int style) { | |
405 SkTypeface::Style skia_style = ConvertFontStyleToSkiaTypefaceStyle(style); | |
406 return skia::AdoptRef(SkTypeface::CreateFromName(family.c_str(), skia_style)); | |
407 } | |
408 | |
397 } // namespace internal | 409 } // namespace internal |
398 | 410 |
399 RenderText::~RenderText() { | 411 RenderText::~RenderText() { |
400 } | 412 } |
401 | 413 |
414 RenderText* RenderText::CreateInstance() { | |
415 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
416 switches::kEnableHarfBuzzRenderText)) | |
Alexei Svitkine (slow)
2014/05/12 15:58:31
Nit: {}'s
ckocagil
2014/05/13 15:03:48
Done.
| |
417 return new RenderTextHarfBuzz; | |
418 return CreateNativeInstance(); | |
419 } | |
420 | |
402 void RenderText::SetText(const base::string16& text) { | 421 void RenderText::SetText(const base::string16& text) { |
403 DCHECK(!composition_range_.IsValid()); | 422 DCHECK(!composition_range_.IsValid()); |
404 if (text_ == text) | 423 if (text_ == text) |
405 return; | 424 return; |
406 text_ = text; | 425 text_ = text; |
407 | 426 |
408 // Adjust ranged styles and colors to accommodate a new text length. | 427 // Adjust ranged styles and colors to accommodate a new text length. |
409 const size_t text_length = text_.length(); | 428 const size_t text_length = text_.length(); |
410 colors_.SetMax(text_length); | 429 colors_.SetMax(text_length); |
411 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) | 430 for (size_t style = 0; style < NUM_TEXT_STYLES; ++style) |
(...skipping 898 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1310 cursor_bounds_ += delta_offset; | 1329 cursor_bounds_ += delta_offset; |
1311 } | 1330 } |
1312 | 1331 |
1313 void RenderText::DrawSelection(Canvas* canvas) { | 1332 void RenderText::DrawSelection(Canvas* canvas) { |
1314 const std::vector<Rect> sel = GetSubstringBounds(selection()); | 1333 const std::vector<Rect> sel = GetSubstringBounds(selection()); |
1315 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) | 1334 for (std::vector<Rect>::const_iterator i = sel.begin(); i < sel.end(); ++i) |
1316 canvas->FillRect(*i, selection_background_focused_color_); | 1335 canvas->FillRect(*i, selection_background_focused_color_); |
1317 } | 1336 } |
1318 | 1337 |
1319 } // namespace gfx | 1338 } // namespace gfx |
OLD | NEW |