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

Side by Side Diff: ui/gfx/render_text_win.cc

Issue 8725002: Draw text via Skia in RenderTextLinux. (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 9 years 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 unified diff | Download patch | Annotate | Revision Log
« ui/gfx/render_text_linux.cc ('K') | « ui/gfx/render_text_linux.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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_win.h" 5 #include "ui/gfx/render_text_win.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/logging.h" 9 #include "base/logging.h"
10 #include "base/stl_util.h" 10 #include "base/stl_util.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "base/utf_string_conversions.h" 12 #include "base/utf_string_conversions.h"
13 #include "base/win/scoped_hdc.h" 13 #include "base/win/scoped_hdc.h"
14 #include "third_party/skia/include/core/SkTypeface.h"
15 #include "ui/gfx/canvas.h" 14 #include "ui/gfx/canvas.h"
16 #include "ui/gfx/canvas_skia.h" 15 #include "ui/gfx/canvas_skia.h"
17 #include "ui/gfx/platform_font.h" 16 #include "ui/gfx/platform_font.h"
18 17
19 namespace { 18 namespace {
20 19
21 // The maximum supported number of Uniscribe runs; a SCRIPT_ITEM is 8 bytes. 20 // The maximum supported number of Uniscribe runs; a SCRIPT_ITEM is 8 bytes.
22 // TODO(msw): Review memory use/failure? Max string length? Alternate approach? 21 // TODO(msw): Review memory use/failure? Max string length? Alternate approach?
23 const int kGuessItems = 100; 22 const int kGuessItems = 100;
24 const int kMaxItems = 10000; 23 const int kMaxItems = 10000;
25 24
26 // The maximum supported number of Uniscribe glyphs; a glyph is 1 word. 25 // The maximum supported number of Uniscribe glyphs; a glyph is 1 word.
27 // TODO(msw): Review memory use/failure? Max string length? Alternate approach? 26 // TODO(msw): Review memory use/failure? Max string length? Alternate approach?
28 const int kMaxGlyphs = 100000; 27 const int kMaxGlyphs = 100000;
29 28
30 // Draw underline and strike through text decorations.
31 // Based on |SkCanvas::DrawTextDecorations()| and constants from:
32 // third_party/skia/src/core/SkTextFormatParams.h
33 void DrawTextRunDecorations(SkCanvas* canvas_skia,
34 const SkPaint& paint,
35 const gfx::internal::TextRun& run,
36 SkScalar x,
37 SkScalar y) {
38 // Fraction of the text size to lower a strike through below the baseline.
39 const SkScalar kStrikeThroughOffset = (-SK_Scalar1 * 6 / 21);
40 // Fraction of the text size to lower an underline below the baseline.
41 const SkScalar kUnderlineOffset = (SK_Scalar1 / 9);
42 // Fraction of the text size to use for a strike through or under-line.
43 const SkScalar kLineThickness = (SK_Scalar1 / 18);
44
45 SkScalar text_size = paint.getTextSize();
46 SkScalar height = SkScalarMul(text_size, kLineThickness);
47 SkRect r;
48
49 r.fLeft = x;
50 r.fRight = x + run.width;
51
52 if (run.underline) {
53 SkScalar offset = SkScalarMulAdd(text_size, kUnderlineOffset, y);
54 r.fTop = offset;
55 r.fBottom = offset + height;
56 canvas_skia->drawRect(r, paint);
57 }
58 if (run.strike) {
59 SkScalar offset = SkScalarMulAdd(text_size, kStrikeThroughOffset, y);
60 r.fTop = offset;
61 r.fBottom = offset + height;
62 canvas_skia->drawRect(r, paint);
63 }
64 }
65
66 // Callback to |EnumEnhMetaFile()| to intercept font creation. 29 // Callback to |EnumEnhMetaFile()| to intercept font creation.
67 int CALLBACK MetaFileEnumProc(HDC hdc, 30 int CALLBACK MetaFileEnumProc(HDC hdc,
68 HANDLETABLE* table, 31 HANDLETABLE* table,
69 CONST ENHMETARECORD* record, 32 CONST ENHMETARECORD* record,
70 int table_entries, 33 int table_entries,
71 LPARAM log_font) { 34 LPARAM log_font) {
72 if (record->iType == EMR_EXTCREATEFONTINDIRECTW) { 35 if (record->iType == EMR_EXTCREATEFONTINDIRECTW) {
73 const EMREXTCREATEFONTINDIRECTW* create_font_record = 36 const EMREXTCREATEFONTINDIRECTW* create_font_record =
74 reinterpret_cast<const EMREXTCREATEFONTINDIRECTW*>(record); 37 reinterpret_cast<const EMREXTCREATEFONTINDIRECTW*>(record);
75 *reinterpret_cast<LOGFONT*>(log_font) = create_font_record->elfw.elfLogFont; 38 *reinterpret_cast<LOGFONT*>(log_font) = create_font_record->elfw.elfLogFont;
(...skipping 321 matching lines...) Expand 10 before | Expand all | Expand 10 after
397 if (!needs_layout_) 360 if (!needs_layout_)
398 return; 361 return;
399 // TODO(msw): Skip complex processing if ScriptIsComplex returns false. 362 // TODO(msw): Skip complex processing if ScriptIsComplex returns false.
400 ItemizeLogicalText(); 363 ItemizeLogicalText();
401 if (!runs_.empty()) 364 if (!runs_.empty())
402 LayoutVisualText(); 365 LayoutVisualText();
403 needs_layout_ = false; 366 needs_layout_ = false;
404 } 367 }
405 368
406 void RenderTextWin::DrawVisualText(Canvas* canvas) { 369 void RenderTextWin::DrawVisualText(Canvas* canvas) {
407 SkCanvas* canvas_skia = canvas->GetSkCanvas(); 370 DCHECK(!needs_layout_);
408 371
409 Point offset(ToViewPoint(Point())); 372 Point offset(GetVisualOrigin());
410 // TODO(msw): Establish a vertical baseline for strings of mixed font heights.
411 size_t height = default_style().font.GetHeight();
412
413 SkScalar x = SkIntToScalar(offset.x()); 373 SkScalar x = SkIntToScalar(offset.x());
414 SkScalar y = SkIntToScalar(offset.y()); 374 SkScalar y = SkIntToScalar(offset.y());
415 // Center the text vertically in the display area.
416 y += (display_rect().height() - height) / 2;
417 // Offset by the font size to account for Skia expecting y to be the bottom.
418 y += default_style().font.GetFontSize();
419
420 SkPaint paint;
421 paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
422 paint.setStyle(SkPaint::kFill_Style);
423 paint.setAntiAlias(true);
424 paint.setSubpixelText(true);
425 paint.setLCDRenderText(true);
426 375
427 std::vector<SkPoint> pos; 376 std::vector<SkPoint> pos;
377
378 internal::SkiaTextRenderer renderer(canvas);
428 for (size_t i = 0; i < runs_.size(); ++i) { 379 for (size_t i = 0; i < runs_.size(); ++i) {
429 // Get the run specified by the visual-to-logical map. 380 // Get the run specified by the visual-to-logical map.
430 internal::TextRun* run = runs_[visual_to_logical_[i]]; 381 internal::TextRun* run = runs_[visual_to_logical_[i]];
431 382
432 // TODO(msw): Font default/fallback and style integration.
433 SkTypeface::Style style = SkTypeface::kNormal;
434 SkTypeface* typeface =
435 SkTypeface::CreateFromName(run->font.GetFontName().c_str(), style);
436 if (typeface) {
437 paint.setTypeface(typeface);
438 // |paint| adds its own ref. Release the ref from CreateFromName.
439 typeface->unref();
440 }
441 paint.setTextSize(run->font.GetFontSize());
442 paint.setColor(run->foreground);
443
444 SkScalar run_x = x;
445
446 // Based on WebCore::skiaDrawText. 383 // Based on WebCore::skiaDrawText.
447 pos.resize(run->glyph_count); 384 pos.resize(run->glyph_count);
385 SkScalar glyph_x = x;
448 for (int glyph = 0; glyph < run->glyph_count; glyph++) { 386 for (int glyph = 0; glyph < run->glyph_count; glyph++) {
449 pos[glyph].set(x + run->offsets[glyph].du, 387 pos[glyph].set(glyph_x + run->offsets[glyph].du,
450 y + run->offsets[glyph].dv); 388 y + run->offsets[glyph].dv);
451 x += SkIntToScalar(run->advance_widths[glyph]); 389 glyph_x += SkIntToScalar(run->advance_widths[glyph]);
452 } 390 }
453 391
454 size_t byte_length = run->glyph_count * sizeof(WORD); 392 renderer.SetFont(run->font);
455 canvas_skia->drawPosText(run->glyphs.get(), byte_length, &pos[0], paint); 393 renderer.SetForegroundColor(run->foreground);
394 renderer.DrawPosText(&pos[0], run->glyphs.get(), run->glyph_count);
456 395
457 if (run->strike || run->underline) 396 if (run->strike || run->underline)
458 DrawTextRunDecorations(canvas_skia, paint, *run, run_x, y); 397 renderer.DrawDecorations(x, y, run->width, run->underline, run->strike);
398
399 x = glyph_x;
459 } 400 }
460 } 401 }
461 402
462 size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) { 403 size_t RenderTextWin::IndexOfAdjacentGrapheme(size_t index, bool next) {
463 EnsureLayout(); 404 EnsureLayout();
464 size_t run_index = GetRunContainingPosition(index); 405 size_t run_index = GetRunContainingPosition(index);
465 internal::TextRun* run = run_index < runs_.size() ? runs_[run_index] : NULL; 406 internal::TextRun* run = run_index < runs_.size() ? runs_[run_index] : NULL;
466 int start = run ? run->range.start() : 0; 407 int start = run ? run->range.start() : 0;
467 int length = run ? run->range.length() : text().length(); 408 int length = run ? run->range.length() : text().length();
468 int ch = index - start; 409 int ch = index - start;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
505 &script_items[0], 446 &script_items[0],
506 &script_items_count); 447 &script_items_count);
507 } 448 }
508 DCHECK(SUCCEEDED(hr)); 449 DCHECK(SUCCEEDED(hr));
509 450
510 if (script_items_count <= 0) 451 if (script_items_count <= 0)
511 return; 452 return;
512 453
513 // Build the list of runs, merge font/underline styles. 454 // Build the list of runs, merge font/underline styles.
514 // TODO(msw): Only break for font changes, not color etc. See TextRun comment. 455 // TODO(msw): Only break for font changes, not color etc. See TextRun comment.
515 // TODO(msw): Apply the overriding selection and composition styles. 456 StyleRanges styles(style_ranges());
516 StyleRanges::const_iterator style = style_ranges().begin(); 457 ApplyCompositionAndSelectionStyles(&styles);
458 StyleRanges::const_iterator style = styles.begin();
517 SCRIPT_ITEM* script_item = &script_items[0]; 459 SCRIPT_ITEM* script_item = &script_items[0];
518 for (int run_break = 0; run_break < text_length;) { 460 for (int run_break = 0; run_break < text_length;) {
519 internal::TextRun* run = new internal::TextRun(); 461 internal::TextRun* run = new internal::TextRun();
520 run->range.set_start(run_break); 462 run->range.set_start(run_break);
521 run->font = style->font; 463 run->font = style->font;
522 run->foreground = style->foreground; 464 run->foreground = style->foreground;
523 run->strike = style->strike; 465 run->strike = style->strike;
524 run->underline = style->underline; 466 run->underline = style->underline;
525 run->script_analysis = script_item->a; 467 run->script_analysis = script_item->a;
526 468
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
741 internal::TextRun* next = runs_[visual_to_logical_[visual_index + 1]]; 683 internal::TextRun* next = runs_[visual_to_logical_[visual_index + 1]];
742 return next->script_analysis.fRTL ? LastSelectionModelInsideRun(next) : 684 return next->script_analysis.fRTL ? LastSelectionModelInsideRun(next) :
743 FirstSelectionModelInsideRun(next); 685 FirstSelectionModelInsideRun(next);
744 } 686 }
745 687
746 RenderText* RenderText::CreateRenderText() { 688 RenderText* RenderText::CreateRenderText() {
747 return new RenderTextWin; 689 return new RenderTextWin;
748 } 690 }
749 691
750 } // namespace gfx 692 } // namespace gfx
OLDNEW
« ui/gfx/render_text_linux.cc ('K') | « ui/gfx/render_text_linux.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698