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

Side by Side Diff: skia/ext/vector_platform_device_cairo_linux.cc

Issue 7847002: Removed unneeded cairo code. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Removed unneeded include Created 9 years, 3 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 | « skia/ext/vector_platform_device_cairo_linux.h ('k') | skia/skia.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) 2011 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 "skia/ext/vector_platform_device_cairo_linux.h"
6
7 #include <cairo.h>
8 #include <cairo-ft.h>
9
10 #include <ft2build.h>
11 #include FT_FREETYPE_H
12
13 #include <map>
14
15 #include "base/lazy_instance.h"
16 #include "base/logging.h"
17 #include "skia/ext/bitmap_platform_device.h"
18 #include "third_party/skia/include/core/SkFontHost.h"
19 #include "third_party/skia/include/core/SkStream.h"
20 #include "third_party/skia/include/core/SkTypeface.h"
21
22 namespace {
23
24 struct FontInfo {
25 SkStream* font_stream;
26 FT_Face ft_face;
27 cairo_font_face_t* cairo_face;
28 cairo_user_data_key_t data_key;
29 };
30
31 typedef std::map<uint32_t, FontInfo> MapFontId2FontInfo;
32 static base::LazyInstance<MapFontId2FontInfo> g_map_font_id_to_font_info(
33 base::LINKER_INITIALIZED);
34
35 // Wrapper for FT_Library that handles initialization and cleanup, and allows
36 // us to use a singleton.
37 class FtLibrary {
38 public:
39 FtLibrary() : library_(NULL) {
40 FT_Error ft_error = FT_Init_FreeType(&library_);
41 if (ft_error) {
42 DLOG(ERROR) << "Cannot initialize FreeType library for " \
43 << "VectorPlatformDeviceCairo.";
44 }
45 }
46
47 ~FtLibrary() {
48 if (library_) {
49 FT_Error ft_error = FT_Done_FreeType(library_);
50 library_ = NULL;
51 DCHECK_EQ(ft_error, 0);
52 }
53 }
54
55 FT_Library library() { return library_; }
56
57 private:
58 FT_Library library_;
59 };
60 static base::LazyInstance<FtLibrary> g_ft_library(base::LINKER_INITIALIZED);
61
62 // Verify cairo surface after creation/modification.
63 bool IsContextValid(cairo_t* context) {
64 return cairo_status(context) == CAIRO_STATUS_SUCCESS;
65 }
66
67 } // namespace
68
69 namespace skia {
70
71 // static
72 SkDevice* VectorPlatformDeviceCairo::CreateDevice(cairo_t* context, int width,
73 int height, bool isOpaque) {
74 // TODO(myhuang): Here we might also have similar issues as those on Windows
75 // (vector_canvas_win.cc, http://crbug.com/18382 & http://crbug.com/18383).
76 // Please note that is_opaque is true when we use this class for printing.
77 // Fallback to bitmap when context is NULL.
78 if (!isOpaque || NULL == context) {
79 return BitmapPlatformDevice::Create(width, height, isOpaque);
80 }
81
82 SkASSERT(cairo_status(context) == CAIRO_STATUS_SUCCESS);
83 SkASSERT(width > 0);
84 SkASSERT(height > 0);
85
86 SkBitmap bitmap;
87 bitmap.setConfig(SkBitmap::kARGB_8888_Config, width, height);
88
89 return new VectorPlatformDeviceCairo(context, bitmap);
90 }
91
92 VectorPlatformDeviceCairo::VectorPlatformDeviceCairo(PlatformSurface context,
93 const SkBitmap& bitmap)
94 : SkDevice(bitmap),
95 context_(context) {
96 SkASSERT(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
97
98 SetPlatformDevice(this, this);
99
100 // Increase the reference count to keep the context alive.
101 cairo_reference(context_);
102
103 transform_.reset();
104 }
105
106 VectorPlatformDeviceCairo::~VectorPlatformDeviceCairo() {
107 // Un-ref |context_| since we referenced it in the constructor.
108 cairo_destroy(context_);
109 }
110
111 PlatformSurface VectorPlatformDeviceCairo::BeginPlatformPaint() {
112 return context_;
113 }
114
115 void VectorPlatformDeviceCairo::DrawToNativeContext(
116 PlatformSurface surface, int x, int y, const PlatformRect* src_rect) {
117 // Should never be called on Linux.
118 SkASSERT(false);
119 }
120
121 SkDevice* VectorPlatformDeviceCairo::onCreateCompatibleDevice(
122 SkBitmap::Config config,
123 int width, int height,
124 bool isOpaque, Usage) {
125 SkASSERT(config == SkBitmap::kARGB_8888_Config);
126 return CreateDevice(NULL, width, height, isOpaque);
127 }
128
129 uint32_t VectorPlatformDeviceCairo::getDeviceCapabilities() {
130 return SkDevice::getDeviceCapabilities() | kVector_Capability;
131 }
132
133 void VectorPlatformDeviceCairo::drawBitmap(const SkDraw& draw,
134 const SkBitmap& bitmap,
135 const SkIRect* srcRectOrNull,
136 const SkMatrix& matrix,
137 const SkPaint& paint) {
138 SkASSERT(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
139
140 // Load the temporary matrix. This is what will translate, rotate and resize
141 // the bitmap.
142 SkMatrix actual_transform(transform_);
143 actual_transform.preConcat(matrix);
144 LoadTransformToContext(actual_transform);
145
146 InternalDrawBitmap(bitmap, 0, 0, paint);
147
148 // Restore the original matrix.
149 LoadTransformToContext(transform_);
150 }
151
152 void VectorPlatformDeviceCairo::drawDevice(const SkDraw& draw,
153 SkDevice* device,
154 int x,
155 int y,
156 const SkPaint& paint) {
157 SkASSERT(device);
158
159 // TODO(myhuang): We may also have to consider http://b/1183870 .
160 drawSprite(draw, device->accessBitmap(false), x, y, paint);
161 }
162
163 void VectorPlatformDeviceCairo::drawPaint(const SkDraw& draw,
164 const SkPaint& paint) {
165 // Bypass the current transformation matrix.
166 LoadIdentityTransformToContext();
167
168 // TODO(myhuang): Is there a better way to do this?
169 SkRect rect;
170 rect.fLeft = 0;
171 rect.fTop = 0;
172 rect.fRight = SkIntToScalar(width() + 1);
173 rect.fBottom = SkIntToScalar(height() + 1);
174 drawRect(draw, rect, paint);
175
176 // Restore the original matrix.
177 LoadTransformToContext(transform_);
178 }
179
180 void VectorPlatformDeviceCairo::drawPath(const SkDraw& draw,
181 const SkPath& path,
182 const SkPaint& paint,
183 const SkMatrix* prePathMatrix,
184 bool pathIsMutable) {
185 if (paint.getPathEffect()) {
186 // Apply the path effect forehand.
187 SkPath path_modified;
188 paint.getFillPath(path, &path_modified);
189
190 // Removes the path effect from the temporary SkPaint object.
191 SkPaint paint_no_effet(paint);
192 SkSafeUnref(paint_no_effet.setPathEffect(NULL));
193
194 // Draw the calculated path.
195 drawPath(draw, path_modified, paint_no_effet);
196 return;
197 }
198
199 // Setup paint color.
200 ApplyPaintColor(paint);
201
202 SkPaint::Style style = paint.getStyle();
203 // Setup fill style.
204 if (style & SkPaint::kFill_Style) {
205 ApplyFillStyle(path);
206 }
207
208 // Setup stroke style.
209 if (style & SkPaint::kStroke_Style) {
210 ApplyStrokeStyle(paint);
211 }
212
213 // Iterate path verbs.
214 // TODO(myhuang): Is there a better way to do this?
215 SkPoint current_points[4];
216 SkPath::Iter iter(path, false);
217 for (SkPath::Verb verb = iter.next(current_points);
218 verb != SkPath::kDone_Verb;
219 verb = iter.next(current_points)) {
220 switch (verb) {
221 case SkPath::kMove_Verb: { // iter.next returns 1 point
222 cairo_move_to(context_, current_points[0].fX, current_points[0].fY);
223 } break;
224
225 case SkPath::kLine_Verb: { // iter.next returns 2 points
226 cairo_line_to(context_, current_points[1].fX, current_points[1].fY);
227 } break;
228
229 case SkPath::kQuad_Verb: { // iter.next returns 3 points
230 // Degree elevation (quadratic to cubic).
231 // c1 = (2 * p1 + p0) / 3
232 // c2 = (2 * p1 + p2) / 3
233 current_points[1].scale(2.); // p1 *= 2.0;
234 SkScalar c1_X = (current_points[1].fX + current_points[0].fX) / 3.;
235 SkScalar c1_Y = (current_points[1].fY + current_points[0].fY) / 3.;
236 SkScalar c2_X = (current_points[1].fX + current_points[2].fX) / 3.;
237 SkScalar c2_Y = (current_points[1].fY + current_points[2].fY) / 3.;
238 cairo_curve_to(context_,
239 c1_X, c1_Y,
240 c2_X, c2_Y,
241 current_points[2].fX, current_points[2].fY);
242 } break;
243
244 case SkPath::kCubic_Verb: { // iter.next returns 4 points
245 cairo_curve_to(context_,
246 current_points[1].fX, current_points[1].fY,
247 current_points[2].fX, current_points[2].fY,
248 current_points[3].fX, current_points[3].fY);
249 } break;
250
251 case SkPath::kClose_Verb: { // iter.next returns 1 point (the last pt).
252 cairo_close_path(context_);
253 } break;
254
255 default: {
256 // Should not reach here!
257 SkASSERT(false);
258 } break;
259 }
260 }
261
262 DoPaintStyle(paint);
263 }
264
265 void VectorPlatformDeviceCairo::drawPoints(const SkDraw& draw,
266 SkCanvas::PointMode mode,
267 size_t count,
268 const SkPoint pts[],
269 const SkPaint& paint) {
270 SkASSERT(pts);
271
272 if (!count)
273 return;
274
275 // Setup paint color.
276 ApplyPaintColor(paint);
277
278 // Setup stroke style.
279 ApplyStrokeStyle(paint);
280
281 switch (mode) {
282 case SkCanvas::kPoints_PointMode: {
283 // There is a bug in Cairo that it won't draw anything when using some
284 // specific caps, e.g. SkPaint::kSquare_Cap. This is because Cairo does
285 // not have enough/ambiguous direction information. One possible work-
286 // around is to draw a really short line.
287 for (size_t i = 0; i < count; ++i) {
288 double x = pts[i].fX;
289 double y = pts[i].fY;
290 cairo_move_to(context_, x, y);
291 cairo_line_to(context_, x+.01, y);
292 }
293 } break;
294
295 case SkCanvas::kLines_PointMode: {
296 if (count % 2) {
297 SkASSERT(false);
298 return;
299 }
300
301 for (size_t i = 0; i < count >> 1; ++i) {
302 double x1 = pts[i << 1].fX;
303 double y1 = pts[i << 1].fY;
304 double x2 = pts[(i << 1) + 1].fX;
305 double y2 = pts[(i << 1) + 1].fY;
306 cairo_move_to(context_, x1, y1);
307 cairo_line_to(context_, x2, y2);
308 }
309 } break;
310
311 case SkCanvas::kPolygon_PointMode: {
312 double x = pts[0].fX;
313 double y = pts[0].fY;
314 cairo_move_to(context_, x, y);
315 for (size_t i = 1; i < count; ++i) {
316 x = pts[i].fX;
317 y = pts[i].fY;
318 cairo_line_to(context_, x, y);
319 }
320 } break;
321
322 default:
323 SkASSERT(false);
324 return;
325 }
326 cairo_stroke(context_);
327 }
328
329 // TODO(myhuang): Embed fonts/texts into PDF surface.
330 // Please NOTE that len records text's length in byte, not uint16_t.
331 void VectorPlatformDeviceCairo::drawPosText(const SkDraw& draw,
332 const void* text,
333 size_t len,
334 const SkScalar pos[],
335 SkScalar constY,
336 int scalarsPerPos,
337 const SkPaint& paint) {
338 SkASSERT(text);
339 SkASSERT(pos);
340 SkASSERT(paint.getTextEncoding() == SkPaint::kGlyphID_TextEncoding);
341 // Each pos should contain either only x, or (x, y).
342 SkASSERT((scalarsPerPos == 1) || (scalarsPerPos == 2));
343
344 if (!len)
345 return;
346
347 // Text color.
348 ApplyPaintColor(paint);
349
350 const uint16_t* glyph_ids = static_cast<const uint16_t*>(text);
351
352 // The style is either kFill_Style or kStroke_Style.
353 if (paint.getStyle() & SkPaint::kStroke_Style) {
354 ApplyStrokeStyle(paint);
355
356 // Draw each glyph by its path.
357 for (size_t i = 0; i < len / sizeof(uint16_t); ++i) {
358 uint16_t glyph_id = glyph_ids[i];
359 SkPath textPath;
360 paint.getTextPath(&glyph_id,
361 sizeof(uint16_t),
362 pos[i * scalarsPerPos],
363 (scalarsPerPos == 1) ?
364 constY :
365 pos[i * scalarsPerPos + 1],
366 &textPath);
367 drawPath(draw, textPath, paint);
368 }
369 } else { // kFill_Style.
370 // Selects correct font.
371 if (!SelectFontById(paint.getTypeface()->uniqueID())) {
372 SkASSERT(false);
373 return;
374 }
375 cairo_set_font_size(context_, paint.getTextSize());
376
377 // Draw glyphs.
378 for (size_t i = 0; i < len / sizeof(uint16_t); ++i) {
379 uint16_t glyph_id = glyph_ids[i];
380
381 cairo_glyph_t glyph;
382 glyph.index = glyph_id;
383 glyph.x = pos[i * scalarsPerPos];
384 glyph.y = (scalarsPerPos == 1) ? constY : pos[i * scalarsPerPos + 1];
385
386 cairo_show_glyphs(context_, &glyph, 1);
387 }
388 }
389 }
390
391 void VectorPlatformDeviceCairo::drawRect(const SkDraw& draw,
392 const SkRect& rect,
393 const SkPaint& paint) {
394 if (paint.getPathEffect()) {
395 // Draw a path instead.
396 SkPath path_orginal;
397 path_orginal.addRect(rect);
398
399 // Apply the path effect to the rect.
400 SkPath path_modified;
401 paint.getFillPath(path_orginal, &path_modified);
402
403 // Removes the path effect from the temporary SkPaint object.
404 SkPaint paint_no_effet(paint);
405 SkSafeUnref(paint_no_effet.setPathEffect(NULL));
406
407 // Draw the calculated path.
408 drawPath(draw, path_modified, paint_no_effet);
409 return;
410 }
411
412 // Setup color.
413 ApplyPaintColor(paint);
414
415 // Setup stroke style.
416 ApplyStrokeStyle(paint);
417
418 // Draw rectangle.
419 cairo_rectangle(context_,
420 rect.fLeft, rect.fTop,
421 rect.fRight - rect.fLeft, rect.fBottom - rect.fTop);
422
423 DoPaintStyle(paint);
424 }
425
426 void VectorPlatformDeviceCairo::drawSprite(const SkDraw& draw,
427 const SkBitmap& bitmap,
428 int x, int y,
429 const SkPaint& paint) {
430 SkASSERT(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
431
432 LoadIdentityTransformToContext();
433
434 InternalDrawBitmap(bitmap, x, y, paint);
435
436 // Restore the original matrix.
437 LoadTransformToContext(transform_);
438 }
439
440 void VectorPlatformDeviceCairo::drawText(const SkDraw& draw,
441 const void* text,
442 size_t byteLength,
443 SkScalar x,
444 SkScalar y,
445 const SkPaint& paint) {
446 // This function isn't used in the code. Verify this assumption.
447 SkASSERT(false);
448 }
449
450
451 void VectorPlatformDeviceCairo::drawTextOnPath(const SkDraw& draw,
452 const void* text,
453 size_t len,
454 const SkPath& path,
455 const SkMatrix* matrix,
456 const SkPaint& paint) {
457 // This function isn't used in the code. Verify this assumption.
458 SkASSERT(false);
459 }
460
461 void VectorPlatformDeviceCairo::drawVertices(const SkDraw& draw,
462 SkCanvas::VertexMode vmode,
463 int vertexCount,
464 const SkPoint vertices[],
465 const SkPoint texs[],
466 const SkColor colors[],
467 SkXfermode* xmode,
468 const uint16_t indices[],
469 int indexCount,
470 const SkPaint& paint) {
471 // This function isn't used in the code. Verify this assumption.
472 SkASSERT(false);
473 }
474
475 void VectorPlatformDeviceCairo::setMatrixClip(const SkMatrix& transform,
476 const SkRegion& region,
477 const SkClipStack&) {
478 clip_region_ = region;
479 if (!clip_region_.isEmpty())
480 LoadClipRegion(clip_region_);
481
482 transform_ = transform;
483 LoadTransformToContext(transform_);
484 }
485
486 void VectorPlatformDeviceCairo::ApplyPaintColor(const SkPaint& paint) {
487 SkColor color = paint.getColor();
488 double a = static_cast<double>(SkColorGetA(color)) / 255.;
489 double r = static_cast<double>(SkColorGetR(color)) / 255.;
490 double g = static_cast<double>(SkColorGetG(color)) / 255.;
491 double b = static_cast<double>(SkColorGetB(color)) / 255.;
492
493 cairo_set_source_rgba(context_, r, g, b, a);
494 }
495
496 void VectorPlatformDeviceCairo::ApplyFillStyle(const SkPath& path) {
497 // Setup fill style.
498 // TODO(myhuang): Cairo does NOT support all skia fill rules!!
499 cairo_set_fill_rule(context_,
500 static_cast<cairo_fill_rule_t>(path.getFillType()));
501 }
502
503 void VectorPlatformDeviceCairo::ApplyStrokeStyle(const SkPaint& paint) {
504 // Line width.
505 cairo_set_line_width(context_, paint.getStrokeWidth());
506
507 // Line join.
508 cairo_set_line_join(context_,
509 static_cast<cairo_line_join_t>(paint.getStrokeJoin()));
510
511 // Line cap.
512 cairo_set_line_cap(context_,
513 static_cast<cairo_line_cap_t>(paint.getStrokeCap()));
514 }
515
516 void VectorPlatformDeviceCairo::DoPaintStyle(const SkPaint& paint) {
517 SkPaint::Style style = paint.getStyle();
518
519 switch (style) {
520 case SkPaint::kFill_Style: {
521 cairo_fill(context_);
522 } break;
523
524 case SkPaint::kStroke_Style: {
525 cairo_stroke(context_);
526 } break;
527
528 case SkPaint::kStrokeAndFill_Style: {
529 cairo_fill_preserve(context_);
530 cairo_stroke(context_);
531 } break;
532
533 default:
534 SkASSERT(false);
535 }
536 }
537
538 void VectorPlatformDeviceCairo::InternalDrawBitmap(const SkBitmap& bitmap,
539 int x, int y,
540 const SkPaint& paint) {
541 SkASSERT(bitmap.getConfig() == SkBitmap::kARGB_8888_Config);
542
543 unsigned char alpha = paint.getAlpha();
544
545 if (alpha == 0)
546 return;
547
548 int src_size_x = bitmap.width();
549 int src_size_y = bitmap.height();
550
551 if (!src_size_x || !src_size_y)
552 return;
553
554 SkAutoLockPixels image_lock(bitmap);
555
556 cairo_surface_t* bitmap_surface =
557 cairo_image_surface_create_for_data(
558 reinterpret_cast<unsigned char*>(bitmap.getPixels()),
559 CAIRO_FORMAT_ARGB32, src_size_x, src_size_y, bitmap.rowBytes());
560
561 cairo_set_source_surface(context_, bitmap_surface, x, y);
562 cairo_paint_with_alpha(context_, static_cast<double>(alpha) / 255.);
563
564 cairo_surface_destroy(bitmap_surface);
565 }
566
567 void VectorPlatformDeviceCairo::LoadClipRegion(const SkRegion& clip) {
568 cairo_reset_clip(context_);
569
570 LoadIdentityTransformToContext();
571
572 // TODO(myhuang): Support non-rect clips.
573 SkIRect bounding = clip.getBounds();
574 cairo_rectangle(context_, bounding.fLeft, bounding.fTop,
575 bounding.fRight - bounding.fLeft,
576 bounding.fBottom - bounding.fTop);
577 cairo_clip(context_);
578
579 // Restore the original matrix.
580 LoadTransformToContext(transform_);
581 }
582
583 void VectorPlatformDeviceCairo::LoadIdentityTransformToContext() {
584 SkMatrix identity;
585 identity.reset();
586 LoadTransformToContext(identity);
587 }
588
589 void VectorPlatformDeviceCairo::LoadTransformToContext(const SkMatrix& matrix) {
590 cairo_matrix_t m;
591 m.xx = matrix[SkMatrix::kMScaleX];
592 m.xy = matrix[SkMatrix::kMSkewX];
593 m.x0 = matrix[SkMatrix::kMTransX];
594 m.yx = matrix[SkMatrix::kMSkewY];
595 m.yy = matrix[SkMatrix::kMScaleY];
596 m.y0 = matrix[SkMatrix::kMTransY];
597 cairo_set_matrix(context_, &m);
598 }
599
600 bool VectorPlatformDeviceCairo::SelectFontById(uint32_t font_id) {
601 DCHECK(IsContextValid(context_));
602 DCHECK(SkFontHost::ValidFontID(font_id));
603
604 FtLibrary* ft_library = g_ft_library.Pointer();
605 if (!ft_library->library())
606 return false;
607
608 // Checks if we have a cache hit.
609 MapFontId2FontInfo* g_font_cache = g_map_font_id_to_font_info.Pointer();
610 DCHECK(g_font_cache);
611
612 MapFontId2FontInfo::iterator it = g_font_cache->find(font_id);
613 if (it != g_font_cache->end()) {
614 cairo_set_font_face(context_, it->second.cairo_face);
615 if (IsContextValid(context_)) {
616 return true;
617 } else {
618 NOTREACHED() << "Cannot set font face in Cairo!";
619 return false;
620 }
621 }
622
623 // Cache missed. We need to load and create the font.
624 FontInfo new_font_info = {0};
625 new_font_info.font_stream = SkFontHost::OpenStream(font_id);
626 DCHECK(new_font_info.font_stream);
627 size_t stream_size = new_font_info.font_stream->getLength();
628 DCHECK(stream_size) << "The Font stream has nothing!";
629
630 FT_Error ft_error = FT_New_Memory_Face(
631 ft_library->library(),
632 static_cast<FT_Byte*>(
633 const_cast<void*>(new_font_info.font_stream->getMemoryBase())),
634 stream_size,
635 0,
636 &new_font_info.ft_face);
637
638 if (ft_error) {
639 new_font_info.font_stream->unref();
640 DLOG(ERROR) << "Cannot create FT_Face!";
641 SkASSERT(false);
642 return false;
643 }
644
645 new_font_info.cairo_face = cairo_ft_font_face_create_for_ft_face(
646 new_font_info.ft_face, 0);
647 DCHECK(new_font_info.cairo_face) << "Cannot create font in Cairo!";
648
649 // Manage |new_font_info.ft_face|'s life by Cairo.
650 cairo_status_t status = cairo_font_face_set_user_data(
651 new_font_info.cairo_face,
652 &new_font_info.data_key,
653 new_font_info.ft_face,
654 reinterpret_cast<cairo_destroy_func_t>(FT_Done_Face));
655
656 if (status != CAIRO_STATUS_SUCCESS) {
657 DLOG(ERROR) << "Cannot set font's user data in Cairo!";
658 cairo_font_face_destroy(new_font_info.cairo_face);
659 FT_Done_Face(new_font_info.ft_face);
660 new_font_info.font_stream->unref();
661 SkASSERT(false);
662 return false;
663 }
664
665 // Inserts |new_font_info| info |g_font_cache|.
666 (*g_font_cache)[font_id] = new_font_info;
667
668 cairo_set_font_face(context_, new_font_info.cairo_face);
669 if (IsContextValid(context_)) {
670 return true;
671 }
672
673 DLOG(ERROR) << "Connot set font face in Cairo!";
674 return false;
675 }
676
677 // static
678 void VectorPlatformDeviceCairo::ClearFontCache() {
679 MapFontId2FontInfo* g_font_cache = g_map_font_id_to_font_info.Pointer();
680 DCHECK(g_font_cache);
681
682 for (MapFontId2FontInfo::iterator it = g_font_cache->begin();
683 it !=g_font_cache->end();
684 ++it) {
685 DCHECK(it->second.cairo_face);
686 DCHECK(it->second.font_stream);
687
688 cairo_font_face_destroy(it->second.cairo_face);
689 // |it->second.ft_face| is handled by Cairo.
690 it->second.font_stream->unref();
691 }
692 g_font_cache->clear();
693 }
694
695 } // namespace skia
OLDNEW
« no previous file with comments | « skia/ext/vector_platform_device_cairo_linux.h ('k') | skia/skia.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698