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

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

Issue 10735009: Delete canvas_win.cc since it is no longer used. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 5 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ui/gfx/canvas.h ('k') | ui/ui.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "ui/gfx/canvas.h"
6
7 #include <limits>
8
9 #include "base/i18n/rtl.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/win/scoped_gdi_object.h"
13 #include "skia/ext/bitmap_platform_device.h"
14 #include "skia/ext/skia_utils_win.h"
15 #include "third_party/skia/include/core/SkShader.h"
16 #include "ui/gfx/color_utils.h"
17 #include "ui/gfx/font.h"
18 #include "ui/gfx/rect.h"
19 #include "ui/gfx/shadow_value.h"
20
21 namespace {
22
23 static inline int Round(double x) {
24 // Why oh why is this not in a standard header?
25 return static_cast<int>(floor(x + 0.5));
26 }
27
28 // We make sure that LTR text we draw in an RTL context is modified
29 // appropriately to make sure it maintains it LTR orientation.
30 void DoDrawText(HDC hdc,
31 const string16& text,
32 RECT* text_bounds,
33 int flags) {
34 // Only adjust string directionality if both of the following are true:
35 // 1. The current locale is RTL.
36 // 2. The string itself has RTL directionality.
37 const wchar_t* string_ptr = text.c_str();
38 int string_size = static_cast<int>(text.length());
39
40 string16 localized_text;
41 if (flags & DT_RTLREADING) {
42 localized_text = text;
43 base::i18n::AdjustStringForLocaleDirection(&localized_text);
44 string_ptr = localized_text.c_str();
45 string_size = static_cast<int>(localized_text.length());
46 }
47
48 DrawText(hdc, string_ptr, string_size, text_bounds, flags);
49 }
50
51 // Compute the windows flags necessary to implement the provided text Canvas
52 // flags.
53 int ComputeFormatFlags(int flags, const string16& text) {
54 // Setting the text alignment explicitly in case it hasn't already been set.
55 // This will make sure that we don't align text to the left on RTL locales
56 // just because no alignment flag was passed to DrawStringInt().
57 if (!(flags & (gfx::Canvas::TEXT_ALIGN_CENTER |
58 gfx::Canvas::TEXT_ALIGN_RIGHT |
59 gfx::Canvas::TEXT_ALIGN_LEFT))) {
60 flags |= gfx::Canvas::DefaultCanvasTextAlignment();
61 }
62
63 // horizontal alignment
64 int f = 0;
65 if (flags & gfx::Canvas::TEXT_ALIGN_CENTER)
66 f |= DT_CENTER;
67 else if (flags & gfx::Canvas::TEXT_ALIGN_RIGHT)
68 f |= DT_RIGHT;
69 else
70 f |= DT_LEFT;
71
72 // vertical alignment
73 if (flags & gfx::Canvas::TEXT_VALIGN_TOP)
74 f |= DT_TOP;
75 else if (flags & gfx::Canvas::TEXT_VALIGN_BOTTOM)
76 f |= DT_BOTTOM;
77 else
78 f |= DT_VCENTER;
79
80 if (flags & gfx::Canvas::MULTI_LINE) {
81 f |= DT_WORDBREAK;
82 if (flags & gfx::Canvas::CHARACTER_BREAK)
83 f |= DT_EDITCONTROL; // Turns on character breaking (not documented)
84 else if (!(flags & gfx::Canvas::NO_ELLIPSIS))
85 f |= DT_WORD_ELLIPSIS;
86 } else {
87 f |= DT_SINGLELINE;
88 }
89
90 if (flags & gfx::Canvas::HIDE_PREFIX)
91 f |= DT_HIDEPREFIX;
92 else if ((flags & gfx::Canvas::SHOW_PREFIX) == 0)
93 f |= DT_NOPREFIX;
94
95 if (!(flags & gfx::Canvas::NO_ELLIPSIS))
96 f |= DT_END_ELLIPSIS;
97
98 // In order to make sure RTL/BiDi strings are rendered correctly, we must
99 // pass the flag DT_RTLREADING to DrawText (when the locale's language is
100 // a right-to-left language) so that Windows does the right thing.
101 //
102 // In addition to correctly displaying text containing both RTL and LTR
103 // elements (for example, a string containing a telephone number within a
104 // sentence in Hebrew, or a sentence in Hebrew that contains a word in
105 // English) this flag also makes sure that if there is not enough space to
106 // display the entire string, the ellipsis is displayed on the left hand side
107 // of the truncated string and not on the right hand side.
108 //
109 // We make a distinction between Chrome UI strings and text coming from a web
110 // page.
111 //
112 // For text coming from a web page we determine the alignment based on the
113 // first character with strong directionality. If the directionality of the
114 // first character with strong directionality in the text is LTR, the
115 // alignment is set to DT_LEFT, and the directionality should not be set as
116 // DT_RTLREADING. If the directionality of the first character with strong
117 // directionality in the text is RTL, its alignment is set to DT_RIGHT, and
118 // its directionality is set as DT_RTLREADING through
119 // FORCE_RTL_DIRECTIONALITY.
120 //
121 // This heuristic doesn't work for Chrome UI strings since even in RTL
122 // locales, some of those might start with English text but we know they're
123 // localized so their directionality should be set as DT_RTLREADING if it
124 // contains strong RTL characters.
125 //
126 // Caveat: If the string is purely LTR, don't set DTL_RTLREADING since when
127 // the flag is set, LRE-PDF don't have the desired effect of rendering
128 // multiline English-only text as LTR.
129 //
130 // Note that if the caller is explicitly requesting displaying the text
131 // using RTL directionality then we respect that and pass DT_RTLREADING to
132 // ::DrawText even if the locale is LTR.
133 int force_rtl = (flags & gfx::Canvas::FORCE_RTL_DIRECTIONALITY);
134 int force_ltr = (flags & gfx::Canvas::FORCE_LTR_DIRECTIONALITY);
135 bool is_rtl = base::i18n::IsRTL();
136 bool string_contains_strong_rtl_chars =
137 base::i18n::StringContainsStrongRTLChars(text);
138 if (force_rtl || (!force_ltr && is_rtl && string_contains_strong_rtl_chars))
139 f |= DT_RTLREADING;
140
141 return f;
142 }
143
144 // Changes the alpha of the given bitmap.
145 // If |fade_to_right| is true then the rect fades from opaque to clear,
146 // otherwise the rect fades from clear to opaque.
147 void FadeBitmapRect(SkDevice& bmp_device,
148 const gfx::Rect& rect,
149 bool fade_to_right) {
150 SkBitmap bmp = bmp_device.accessBitmap(true);
151 DCHECK_EQ(SkBitmap::kARGB_8888_Config, bmp.config());
152 SkAutoLockPixels lock(bmp);
153 float total_width = static_cast<float>(rect.width());
154
155 for (int x = rect.x(); x < rect.right(); x++) {
156 float cur_width = static_cast<float>(fade_to_right ?
157 rect.right() - x : x - rect.x());
158 // We want the fade effect to go from 0.2 to 1.0.
159 float alpha_percent = ((cur_width / total_width) * 0.8f) + 0.2f;
160
161 for (int y = rect.y(); y < rect.bottom(); y++) {
162 SkColor color = bmp.getColor(x, y);
163 SkAlpha alpha = static_cast<SkAlpha>(SkColorGetA(color) * alpha_percent);
164 *bmp.getAddr32(x, y) = SkPreMultiplyColor(SkColorSetA(color, alpha));
165 }
166 }
167 }
168
169 // DrawText() doesn't support alpha channels. To create a transparent background
170 // this function draws black on white. It then uses the intensity of black
171 // to determine how much alpha to use. The text is drawn in |gfx_text_rect| and
172 // clipped to |gfx_draw_rect|.
173 void DrawTextAndClearBackground(SkCanvas* bmp_canvas,
174 HFONT font,
175 COLORREF text_color,
176 const string16& text,
177 int flags,
178 const gfx::Rect& gfx_text_rect,
179 const gfx::Rect& gfx_draw_rect) {
180 skia::ScopedPlatformPaint scoped_platform_paint(bmp_canvas);
181 HDC hdc = scoped_platform_paint.GetPlatformSurface();
182
183 // Clear the background by filling with white.
184 HBRUSH fill_brush = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
185 HANDLE old_brush = SelectObject(hdc, fill_brush);
186 RECT draw_rect = gfx_draw_rect.ToRECT();
187 FillRect(hdc, &draw_rect, fill_brush);
188 SelectObject(hdc, old_brush);
189
190 // Set black text with transparent background.
191 SetBkMode(hdc, TRANSPARENT);
192 SetTextColor(hdc, 0);
193
194 // Draw the text.
195 int save_dc_id = SaveDC(hdc);
196 // Clip the text to the draw destination.
197 IntersectClipRect(hdc, draw_rect.left, draw_rect.top,
198 draw_rect.right, draw_rect.bottom);
199 SelectObject(hdc, font);
200 RECT text_rect = gfx_text_rect.ToRECT();
201 DoDrawText(hdc, text, &text_rect,
202 ComputeFormatFlags(flags, text));
203 RestoreDC(hdc, save_dc_id);
204
205 BYTE text_color_r = GetRValue(text_color);
206 BYTE text_color_g = GetGValue(text_color);
207 BYTE text_color_b = GetBValue(text_color);
208
209 SkBitmap bmp = bmp_canvas->getTopDevice()->accessBitmap(true);
210 DCHECK_EQ(SkBitmap::kARGB_8888_Config, bmp.config());
211 SkAutoLockPixels lock(bmp);
212
213 // At this point the bitmap has black text on white.
214 // The intensity of black tells us the alpha value of the text.
215 for (int y = draw_rect.top; y < draw_rect.bottom; y++) {
216 for (int x = draw_rect.left; x < draw_rect.right; x++) {
217 // Gets the color directly. DrawText doesn't premultiply alpha so
218 // using SkBitmap::getColor() won't work here.
219 SkColor color = *bmp.getAddr32(x, y);
220 // Calculate the alpha using the luminance. Since this is black text
221 // on a white background the luminosity must be inverted.
222 BYTE alpha = 0xFF - color_utils::GetLuminanceForColor(color);
223 *bmp.getAddr32(x, y) = SkPreMultiplyColor(
224 SkColorSetARGB(alpha, text_color_r, text_color_g, text_color_b));
225 }
226 }
227 }
228
229 // Draws the given text with a fade out gradient. |bmp_device| is a bitmap
230 // that is used to temporary drawing. The text is drawn in |text_rect| and
231 // clipped to |draw_rect|.
232 void DrawTextGradientPart(HDC hdc,
233 SkCanvas* bmp_canvas,
234 const string16& text,
235 SkColor color,
236 HFONT font,
237 const gfx::Rect& text_rect,
238 const gfx::Rect& draw_rect,
239 bool fade_to_right,
240 int flags) {
241 DrawTextAndClearBackground(bmp_canvas, font, skia::SkColorToCOLORREF(color),
242 text, flags, text_rect, draw_rect);
243 FadeBitmapRect(*bmp_canvas->getTopDevice(), draw_rect, fade_to_right);
244 BLENDFUNCTION blend = {AC_SRC_OVER, 0, 255, AC_SRC_ALPHA};
245
246 skia::ScopedPlatformPaint scoped_platform_paint(bmp_canvas);
247 HDC bmp_hdc = scoped_platform_paint.GetPlatformSurface();
248 AlphaBlend(hdc, draw_rect.x(), draw_rect.y(), draw_rect.width(),
249 draw_rect.height(), bmp_hdc, draw_rect.x(), draw_rect.y(),
250 draw_rect.width(), draw_rect.height(), blend);
251 }
252
253 enum PrimarySide {
254 PrimaryOnLeft,
255 PrimaryOnRight,
256 };
257
258 // Divides |rect| horizontally into a |primary| of width |primary_width| and a
259 // |secondary| taking up the remainder.
260 void DivideRect(const gfx::Rect& rect,
261 PrimarySide primary_side,
262 int primary_width,
263 gfx::Rect* primary,
264 gfx::Rect* secondary) {
265 *primary = rect;
266 *secondary = rect;
267 int remainder = rect.width() - primary_width;
268
269 switch (primary_side) {
270 case PrimaryOnLeft:
271 primary->Inset(0, 0, remainder, 0);
272 secondary->Inset(primary_width, 0, 0, 0);
273 break;
274 case PrimaryOnRight:
275 primary->Inset(remainder, 0, 0, 0);
276 secondary->Inset(0, 0, primary_width, 0);
277 break;
278 }
279 }
280
281 } // anonymous namespace
282
283 namespace gfx {
284
285 // static
286 void Canvas::SizeStringInt(const string16& text,
287 const gfx::Font& font,
288 int* width, int* height,
289 int flags) {
290 // Clamp the max amount of text we'll measure to 2K. When the string is
291 // actually drawn, it will be clipped to whatever size box is provided, and
292 // the time to do that doesn't depend on the length being clipped off.
293 const int kMaxStringLength = 2048 - 1; // So the trailing \0 fits in 2K.
294 string16 clamped_string(text.substr(0, kMaxStringLength));
295
296 if (*width == 0) {
297 // If multi-line + character break are on, the computed width will be one
298 // character wide (useless). Furthermore, if in this case the provided text
299 // contains very long "words" (substrings without a word-breaking point),
300 // DrawText() can run extremely slowly (e.g. several seconds). So in this
301 // case, we turn character breaking off to get a more accurate "desired"
302 // width and avoid the slowdown.
303 int multiline_charbreak =
304 gfx::Canvas::MULTI_LINE | gfx::Canvas::CHARACTER_BREAK;
305 if ((flags & multiline_charbreak) == multiline_charbreak)
306 flags &= ~gfx::Canvas::CHARACTER_BREAK;
307
308 // Weird undocumented behavior: if the width is 0, DoDrawText() won't
309 // calculate a size at all. So set it to 1, which it will then change.
310 if (!text.empty())
311 *width = 1;
312 }
313 RECT r = { 0, 0, *width, *height };
314
315 HDC dc = GetDC(NULL);
316 HFONT old_font = static_cast<HFONT>(SelectObject(dc, font.GetNativeFont()));
317 DoDrawText(dc, clamped_string, &r,
318 ComputeFormatFlags(flags, clamped_string) | DT_CALCRECT);
319 SelectObject(dc, old_font);
320 ReleaseDC(NULL, dc);
321
322 *width = r.right;
323 *height = r.bottom;
324 }
325
326 void Canvas::DrawStringInt(const string16& text,
327 HFONT font,
328 SkColor color,
329 const gfx::Rect& text_bounds,
330 int flags) {
331 SkRect fclip;
332 if (!canvas_->getClipBounds(&fclip))
333 return;
334 RECT text_rect = text_bounds.ToRECT();
335 SkIRect clip;
336 fclip.round(&clip);
337 if (!clip.intersect(skia::RECTToSkIRect(text_rect)))
338 return;
339
340 // Clamp the max amount of text we'll draw to 32K. There seem to be bugs in
341 // DrawText() if you e.g. ask it to character-break a no-whitespace string of
342 // length > 43680 (for which it draws nothing), and since we clamped to 2K in
343 // SizeStringInt() we're unlikely to be able to display this much anyway.
344 const int kMaxStringLength = 32768 - 1; // So the trailing \0 fits in 32K.
345 string16 clamped_string(text.substr(0, kMaxStringLength));
346
347 HDC dc;
348 HFONT old_font;
349 {
350 skia::ScopedPlatformPaint scoped_platform_paint(canvas_);
351 dc = scoped_platform_paint.GetPlatformSurface();
352 SetBkMode(dc, TRANSPARENT);
353 old_font = (HFONT)SelectObject(dc, font);
354 COLORREF brush_color = RGB(SkColorGetR(color), SkColorGetG(color),
355 SkColorGetB(color));
356 SetTextColor(dc, brush_color);
357
358 int f = ComputeFormatFlags(flags, clamped_string);
359 DoDrawText(dc, clamped_string, &text_rect, f);
360 }
361
362 // Restore the old font. This way we don't have to worry if the caller
363 // deletes the font and the DC lives longer.
364 SelectObject(dc, old_font);
365
366 // Windows will have cleared the alpha channel of the text we drew. Assume
367 // we're drawing to an opaque surface, or at least the text rect area is
368 // opaque.
369 skia::MakeOpaque(canvas_, clip.fLeft, clip.fTop, clip.width(),
370 clip.height());
371 }
372
373 void Canvas::DrawStringWithShadows(const string16& text,
374 const gfx::Font& font,
375 SkColor color,
376 const gfx::Rect& text_bounds,
377 int flags,
378 const ShadowValues& shadows) {
379 DLOG_IF(WARNING, !shadows.empty()) << "Text shadow not implemented.";
380
381 DrawStringInt(text, font.GetNativeFont(), color, text_bounds, flags);
382 }
383
384 // Checks each pixel immediately adjacent to the given pixel in the bitmap. If
385 // any of them are not the halo color, returns true. This defines the halo of
386 // pixels that will appear around the text. Note that we have to check each
387 // pixel against both the halo color and transparent since DrawStringWithHalo
388 // will modify the bitmap as it goes, and clears pixels shouldn't count as
389 // changed.
390 static bool pixelShouldGetHalo(const SkBitmap& bitmap,
391 int x, int y,
392 SkColor halo_color) {
393 if (x > 0 &&
394 *bitmap.getAddr32(x - 1, y) != halo_color &&
395 *bitmap.getAddr32(x - 1, y) != 0)
396 return true; // Touched pixel to the left.
397 if (x < bitmap.width() - 1 &&
398 *bitmap.getAddr32(x + 1, y) != halo_color &&
399 *bitmap.getAddr32(x + 1, y) != 0)
400 return true; // Touched pixel to the right.
401 if (y > 0 &&
402 *bitmap.getAddr32(x, y - 1) != halo_color &&
403 *bitmap.getAddr32(x, y - 1) != 0)
404 return true; // Touched pixel above.
405 if (y < bitmap.height() - 1 &&
406 *bitmap.getAddr32(x, y + 1) != halo_color &&
407 *bitmap.getAddr32(x, y + 1) != 0)
408 return true; // Touched pixel below.
409 return false;
410 }
411
412 void Canvas::DrawStringWithHalo(const string16& text,
413 const gfx::Font& font,
414 SkColor text_color,
415 SkColor halo_color_in,
416 int x, int y, int w, int h,
417 int flags) {
418 // Some callers will have semitransparent halo colors, which we don't handle
419 // (since the resulting image can have 1-bit transparency only).
420 SkColor halo_color = SkColorSetA(halo_color_in, 0xFF);
421
422 // Create a temporary buffer filled with the halo color. It must leave room
423 // for the 1-pixel border around the text.
424 Size size(w + 2, h + 2);
425 Canvas text_canvas(size, true);
426 SkPaint bkgnd_paint;
427 bkgnd_paint.setColor(halo_color);
428 text_canvas.DrawRect(gfx::Rect(size), bkgnd_paint);
429
430 // Draw the text into the temporary buffer. This will have correct
431 // ClearType since the background color is the same as the halo color.
432 text_canvas.DrawStringInt(text, font, text_color, 1, 1, w, h, flags);
433
434 // Windows will have cleared the alpha channel for the pixels it drew. Make it
435 // opaque. We have to do this first since pixelShouldGetHalo will check for
436 // 0 to see if a pixel has been modified to transparent, and black text that
437 // Windows draw will look transparent to it!
438 skia::MakeOpaque(text_canvas.sk_canvas(), 0, 0, size.width(), size.height());
439
440 uint32_t halo_premul = SkPreMultiplyColor(halo_color);
441 SkBitmap& text_bitmap = const_cast<SkBitmap&>(
442 skia::GetTopDevice(*text_canvas.sk_canvas())->accessBitmap(true));
443 for (int cur_y = 0; cur_y < h + 2; cur_y++) {
444 uint32_t* text_row = text_bitmap.getAddr32(0, cur_y);
445 for (int cur_x = 0; cur_x < w + 2; cur_x++) {
446 if (text_row[cur_x] == halo_premul) {
447 // This pixel was not touched by the text routines. See if it borders
448 // a touched pixel in any of the 4 directions (not diagonally).
449 if (!pixelShouldGetHalo(text_bitmap, cur_x, cur_y, halo_premul))
450 text_row[cur_x] = 0; // Make transparent.
451 } else {
452 text_row[cur_x] |= 0xff << SK_A32_SHIFT; // Make opaque.
453 }
454 }
455 }
456
457 // Draw the halo bitmap with blur.
458 DrawImageInt(text_bitmap, x - 1, y - 1);
459 }
460
461 void Canvas::DrawFadeTruncatingString(
462 const string16& text,
463 TruncateFadeMode truncate_mode,
464 size_t desired_characters_to_truncate_from_head,
465 const gfx::Font& font,
466 SkColor color,
467 const gfx::Rect& display_rect) {
468 int flags = NO_ELLIPSIS;
469
470 // If the whole string fits in the destination then just draw it directly.
471 int total_string_width = 0;
472 int total_string_height = 0;
473 SizeStringInt(text, font, &total_string_width, &total_string_height,
474 flags | TEXT_VALIGN_TOP);
475
476 if (total_string_width <= display_rect.width()) {
477 DrawStringInt(text, font, color, display_rect.x(), display_rect.y(),
478 display_rect.width(), display_rect.height(), 0);
479 return;
480 }
481
482 int average_character_width = font.GetAverageCharacterWidth();
483 int clipped_string_width = total_string_width - display_rect.width();
484 // Clip the string by drawing it to the left by |offset_x|.
485 int offset_x = 0;
486 switch (truncate_mode) {
487 case TruncateFadeHead:
488 offset_x = clipped_string_width;
489 break;
490 case TruncateFadeHeadAndTail:
491 DCHECK_GT(desired_characters_to_truncate_from_head, 0u);
492 // Get the width of the beginning of the string we're clipping.
493 string16 clipped_head_string =
494 text.substr(0, desired_characters_to_truncate_from_head);
495 int clipped_width;
496 int clipped_height;
497 SizeStringInt(clipped_head_string, font,
498 &clipped_width, &clipped_height, flags);
499
500 // This is the offset at which we start drawing. This causes the
501 // beginning of the string to get clipped.
502 offset_x = clipped_width;
503
504 // Due to the fade effect the first character is hard to see.
505 // We want to make sure that the first character starting at
506 // |desired_characters_to_truncate_from_head| is readable so we reduce
507 // the offset by a little bit.
508 offset_x = std::max(0, Round(offset_x - average_character_width * 2));
509
510 // If the offset is so large that there's empty space at the tail
511 // then reduce the offset so we can use up the empty space.
512 offset_x = std::min(offset_x, clipped_string_width);
513 break;
514 }
515 bool is_truncating_head = offset_x > 0;
516 bool is_truncating_tail = clipped_string_width > offset_x;
517
518 bool is_rtl = (ComputeFormatFlags(flags, text) & DT_RTLREADING) != 0;
519 // |is_rtl| tells us if the given text is right to left or not. |is_rtl| can
520 // be false even if the UI is set to a right to left language.
521 // Now, normally, we right align all text if the UI is set to a right to
522 // left language. In this case though we don't want that because we render
523 // the ends of the string ourselves.
524 if (!is_rtl)
525 flags |= TEXT_ALIGN_LEFT;
526
527 // Fade in/out about 2.5 characters of the beginning/end of the string.
528 // The .5 here is helpful if one of the characters is a space.
529 // Use a quarter of the display width if the string is very short.
530 int gradient_width = Round(std::min(average_character_width * 2.5,
531 display_rect.width() / 4.0));
532
533 // Move the origin to |display_rect.origin()|. This simplifies all the
534 // drawing so that both the source and destination can be (0,0).
535 canvas_->save(SkCanvas::kMatrix_SaveFlag);
536 Translate(display_rect.origin());
537
538 gfx::Rect solid_part(gfx::Point(), display_rect.size());
539 gfx::Rect head_part;
540 gfx::Rect tail_part;
541 if (is_truncating_head)
542 DivideRect(solid_part, is_rtl ? PrimaryOnRight : PrimaryOnLeft,
543 gradient_width, &head_part, &solid_part);
544 if (is_truncating_tail)
545 DivideRect(solid_part, is_rtl ? PrimaryOnLeft : PrimaryOnRight,
546 gradient_width, &tail_part, &solid_part);
547
548 // Grow |display_rect| by |offset_x|.
549 gfx::Rect text_rect(gfx::Point(), display_rect.size());
550 if (!is_rtl)
551 text_rect.set_x(text_rect.x() - offset_x);
552 text_rect.set_width(text_rect.width() + offset_x);
553
554 // Create a temporary bitmap to draw the gradient to.
555 scoped_ptr<SkCanvas> gradient_canvas(skia::CreateBitmapCanvas(
556 display_rect.width(), display_rect.height(), false));
557 gradient_canvas->clear(SkColorSetARGB(0, 0, 0, 0));
558
559 {
560 skia::ScopedPlatformPaint scoped_platform_paint(canvas_);
561 HDC hdc = scoped_platform_paint.GetPlatformSurface();
562 if (is_truncating_head)
563 DrawTextGradientPart(hdc, gradient_canvas.get(), text, color,
564 font.GetNativeFont(), text_rect, head_part, is_rtl,
565 flags);
566 if (is_truncating_tail)
567 DrawTextGradientPart(hdc, gradient_canvas.get(), text, color,
568 font.GetNativeFont(), text_rect, tail_part, !is_rtl,
569 flags);
570 }
571
572 // Draw the solid part.
573 canvas_->save(SkCanvas::kClip_SaveFlag);
574 ClipRect(solid_part);
575 DrawStringInt(text, font, color,
576 text_rect.x(), text_rect.y(),
577 text_rect.width(), text_rect.height(),
578 flags);
579 canvas_->restore();
580 canvas_->restore();
581 }
582
583 } // namespace gfx
OLDNEW
« no previous file with comments | « ui/gfx/canvas.h ('k') | ui/ui.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698