OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "printing/pdf_ps_metafile_linux.h" | 5 #include "printing/pdf_ps_metafile_linux.h" |
6 | 6 |
7 #include <stdio.h> | 7 #include <stdio.h> |
8 | 8 |
9 #include <cairo.h> | 9 #include <cairo.h> |
| 10 #include <cairo-ft.h> |
10 #include <cairo-pdf.h> | 11 #include <cairo-pdf.h> |
11 #include <cairo-ps.h> | 12 #include <cairo-ps.h> |
12 | 13 |
| 14 #include <ft2build.h> |
| 15 #include FT_FREETYPE_H |
| 16 |
| 17 #include <map> |
| 18 |
13 #include "base/file_util.h" | 19 #include "base/file_util.h" |
14 #include "base/logging.h" | 20 #include "base/logging.h" |
| 21 #include "base/singleton.h" |
| 22 #include "third_party/skia/include/core/SkFontHost.h" |
| 23 #include "third_party/skia/include/core/SkStream.h" |
| 24 #include "third_party/skia/include/core/SkTypeface.h" |
15 | 25 |
16 namespace { | 26 namespace { |
17 | 27 |
| 28 FT_Library g_ft_library = NULL; // handle to FreeType library. |
| 29 |
| 30 struct FontInfo { |
| 31 SkStream* font_stream; |
| 32 FT_Face ft_face; |
| 33 cairo_font_face_t* cairo_face; |
| 34 cairo_user_data_key_t data_key; |
| 35 }; |
| 36 |
| 37 typedef std::map<uint32_t, FontInfo> MapFontId2FontInfo; |
| 38 |
| 39 // NOTE: Only call this function when no further rendering will be performed, |
| 40 // and/or the metafile is closed. |
| 41 void CleanUpFonts() { |
| 42 MapFontId2FontInfo* g_font_cache = Singleton<MapFontId2FontInfo>::get(); |
| 43 DCHECK(g_font_cache); |
| 44 |
| 45 for (MapFontId2FontInfo::iterator it = g_font_cache->begin(); |
| 46 it !=g_font_cache->end(); |
| 47 ++it) { |
| 48 DCHECK(it->second.cairo_face); |
| 49 DCHECK(it->second.font_stream); |
| 50 |
| 51 cairo_font_face_destroy(it->second.cairo_face); |
| 52 // |it->second.ft_face| is handled by Cairo. |
| 53 it->second.font_stream->unref(); |
| 54 } |
| 55 g_font_cache->clear(); |
| 56 } |
| 57 |
| 58 void CleanUpFreeType() { |
| 59 if (g_ft_library) { |
| 60 FT_Error ft_error = FT_Done_FreeType(g_ft_library); |
| 61 g_ft_library = NULL; |
| 62 DCHECK_EQ(ft_error, 0); |
| 63 } |
| 64 } |
| 65 |
18 // Tests if |surface| is valid. | 66 // Tests if |surface| is valid. |
19 bool IsSurfaceValid(cairo_surface_t* surface) { | 67 bool IsSurfaceValid(cairo_surface_t* surface) { |
20 return cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS; | 68 return cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS; |
21 } | 69 } |
22 | 70 |
23 // Tests if |context| is valid. | 71 // Tests if |context| is valid. |
24 bool IsContextValid(cairo_t* context) { | 72 bool IsContextValid(cairo_t* context) { |
25 return cairo_status(context) == CAIRO_STATUS_SUCCESS; | 73 return cairo_status(context) == CAIRO_STATUS_SUCCESS; |
26 } | 74 } |
27 | 75 |
(...skipping 13 matching lines...) Expand all Loading... |
41 } | 89 } |
42 } | 90 } |
43 | 91 |
44 // Callback function for Cairo to write PDF/PS stream. | 92 // Callback function for Cairo to write PDF/PS stream. |
45 // |dst_buffer| is actually a pointer of type `std::string*`. | 93 // |dst_buffer| is actually a pointer of type `std::string*`. |
46 cairo_status_t WriteCairoStream(void* dst_buffer, | 94 cairo_status_t WriteCairoStream(void* dst_buffer, |
47 const unsigned char* src_data, | 95 const unsigned char* src_data, |
48 unsigned int src_data_length) { | 96 unsigned int src_data_length) { |
49 DCHECK(dst_buffer); | 97 DCHECK(dst_buffer); |
50 DCHECK(src_data); | 98 DCHECK(src_data); |
51 DCHECK(src_data_length > 0); | 99 DCHECK_GT(src_data_length, 0u); |
52 | 100 |
53 std::string* buffer = reinterpret_cast<std::string*>(dst_buffer); | 101 std::string* buffer = reinterpret_cast<std::string*>(dst_buffer); |
54 buffer->append(reinterpret_cast<const char*>(src_data), src_data_length); | 102 buffer->append(reinterpret_cast<const char*>(src_data), src_data_length); |
55 | 103 |
56 return CAIRO_STATUS_SUCCESS; | 104 return CAIRO_STATUS_SUCCESS; |
57 } | 105 } |
58 | 106 |
59 } // namespace | 107 } // namespace |
60 | 108 |
61 namespace printing { | 109 namespace printing { |
62 | 110 |
63 PdfPsMetafile::PdfPsMetafile(const FileFormat& format) | 111 PdfPsMetafile::PdfPsMetafile(const FileFormat& format) |
64 : format_(format), | 112 : format_(format), |
65 surface_(NULL), context_(NULL), | 113 surface_(NULL), context_(NULL), |
66 page_surface_(NULL), page_context_(NULL) { | 114 page_surface_(NULL), page_context_(NULL) { |
67 } | 115 } |
68 | 116 |
69 PdfPsMetafile::~PdfPsMetafile() { | 117 PdfPsMetafile::~PdfPsMetafile() { |
70 // Releases resources if we forgot to do so. | 118 // Releases all resources if we forgot to do so. |
71 CleanUp(); | 119 CleanUpAll(); |
72 } | 120 } |
73 | 121 |
74 bool PdfPsMetafile::Init() { | 122 bool PdfPsMetafile::Init() { |
75 // We need to check at least these two members to ensure Init() has not been | 123 // We need to check at least these two members to ensure Init() has not been |
76 // called before. Passing these two checks also implies that surface_, | 124 // called before. Passing these two checks also implies that surface_, |
77 // page_surface_, and page_context_ are NULL, and current_page_ is empty. | 125 // page_surface_, and page_context_ are NULL, and current_page_ is empty. |
78 DCHECK(!context_); | 126 DCHECK(!context_); |
79 DCHECK(all_pages_.empty()); | 127 DCHECK(all_pages_.empty()); |
| 128 DCHECK(!g_ft_library); |
80 | 129 |
81 // Create an 1 by 1 Cairo surface for entire PDF/PS file. | 130 // Initializes FreeType library. |
| 131 FT_Error ft_error = FT_Init_FreeType(&g_ft_library); |
| 132 if (ft_error) { |
| 133 DLOG(ERROR) << "Cannot initialize FreeType library for PdfPsMetafile."; |
| 134 g_ft_library = NULL; |
| 135 return false; |
| 136 } |
| 137 |
| 138 // Creates an 1 by 1 Cairo surface for entire PDF/PS file. |
82 // The size for each page will be overwritten later in StartPage(). | 139 // The size for each page will be overwritten later in StartPage(). |
83 switch (format_) { | 140 switch (format_) { |
84 case PDF: { | 141 case PDF: { |
85 surface_ = cairo_pdf_surface_create_for_stream(WriteCairoStream, | 142 surface_ = cairo_pdf_surface_create_for_stream(WriteCairoStream, |
86 &all_pages_, 1, 1); | 143 &all_pages_, 1, 1); |
87 } | 144 } |
88 break; | 145 break; |
89 | 146 |
90 case PS: { | 147 case PS: { |
91 surface_ = cairo_ps_surface_create_for_stream(WriteCairoStream, | 148 surface_ = cairo_ps_surface_create_for_stream(WriteCairoStream, |
92 &all_pages_, 1, 1); | 149 &all_pages_, 1, 1); |
93 } | 150 } |
94 break; | 151 break; |
95 | 152 |
96 default: | 153 default: |
97 NOTREACHED(); | 154 NOTREACHED(); |
98 return false; | 155 return false; |
99 } | 156 } |
100 | 157 |
101 // Cairo always returns a valid pointer. | 158 // Cairo always returns a valid pointer. |
102 // Hence, we have to check if it points to a "nil" object. | 159 // Hence, we have to check if it points to a "nil" object. |
103 if (!IsSurfaceValid(surface_)) { | 160 if (!IsSurfaceValid(surface_)) { |
104 DLOG(ERROR) << "Cannot create Cairo surface for PdfPsMetafile!"; | 161 DLOG(ERROR) << "Cannot create Cairo surface for PdfPsMetafile!"; |
105 CleanUpSurface(&surface_); | 162 CleanUpSurface(&surface_); |
| 163 CleanUpFreeType(); |
106 return false; | 164 return false; |
107 } | 165 } |
108 | 166 |
109 // Create a context. | 167 // Creates a context. |
110 context_ = cairo_create(surface_); | 168 context_ = cairo_create(surface_); |
111 if (!IsContextValid(context_)) { | 169 if (!IsContextValid(context_)) { |
112 DLOG(ERROR) << "Cannot create Cairo context for PdfPsMetafile!"; | 170 DLOG(ERROR) << "Cannot create Cairo context for PdfPsMetafile!"; |
113 CleanUpContext(&context_); | 171 CleanUpContext(&context_); |
114 CleanUpSurface(&surface_); | 172 CleanUpSurface(&surface_); |
| 173 CleanUpFreeType(); |
115 return false; | 174 return false; |
116 } | 175 } |
117 | 176 |
118 return true; | 177 return true; |
119 } | 178 } |
120 | 179 |
121 bool PdfPsMetafile::Init(const void* src_buffer, size_t src_buffer_size) { | 180 bool PdfPsMetafile::Init(const void* src_buffer, size_t src_buffer_size) { |
122 // We need to check at least these two members to ensure Init() has not been | 181 // We need to check at least these two members to ensure Init() has not been |
123 // called before. Passing these two checks also implies that surface_, | 182 // called before. Passing these two checks also implies that surface_, |
124 // page_surface_, and page_context_ are NULL, and current_page_ is empty. | 183 // page_surface_, and page_context_ are NULL, and current_page_ is empty. |
(...skipping 13 matching lines...) Expand all Loading... |
138 cairo_t* PdfPsMetafile::StartPage(double width_in_points, | 197 cairo_t* PdfPsMetafile::StartPage(double width_in_points, |
139 double height_in_points) { | 198 double height_in_points) { |
140 DCHECK(IsSurfaceValid(surface_)); | 199 DCHECK(IsSurfaceValid(surface_)); |
141 DCHECK(IsContextValid(context_)); | 200 DCHECK(IsContextValid(context_)); |
142 // Passing this check implies page_surface_ is NULL, and current_page_ is | 201 // Passing this check implies page_surface_ is NULL, and current_page_ is |
143 // empty. | 202 // empty. |
144 DCHECK(!page_context_); | 203 DCHECK(!page_context_); |
145 DCHECK_GT(width_in_points, 0.); | 204 DCHECK_GT(width_in_points, 0.); |
146 DCHECK_GT(height_in_points, 0.); | 205 DCHECK_GT(height_in_points, 0.); |
147 | 206 |
148 // Create a target surface for the new page. | 207 // Creates a target surface for the new page. |
149 // Cairo 1.6.0 does NOT allow the first argument be NULL, | 208 // Cairo 1.6.0 does NOT allow the first argument be NULL, |
150 // but some newer versions do support NULL pointer. | 209 // but some newer versions do support NULL pointer. |
151 switch (format_) { | 210 switch (format_) { |
152 case PDF: { | 211 case PDF: { |
153 page_surface_ = cairo_pdf_surface_create_for_stream(WriteCairoStream, | 212 page_surface_ = cairo_pdf_surface_create_for_stream(WriteCairoStream, |
154 ¤t_page_, | 213 ¤t_page_, |
155 width_in_points, | 214 width_in_points, |
156 height_in_points); | 215 height_in_points); |
157 } | 216 } |
158 break; | 217 break; |
159 | 218 |
160 case PS: { | 219 case PS: { |
161 page_surface_ = cairo_ps_surface_create_for_stream(WriteCairoStream, | 220 page_surface_ = cairo_ps_surface_create_for_stream(WriteCairoStream, |
162 ¤t_page_, | 221 ¤t_page_, |
163 width_in_points, | 222 width_in_points, |
164 height_in_points); | 223 height_in_points); |
165 } | 224 } |
166 break; | 225 break; |
167 | 226 |
168 default: | 227 default: |
169 NOTREACHED(); | 228 NOTREACHED(); |
170 CleanUp(); | 229 CleanUpAll(); |
171 return NULL; | 230 return NULL; |
172 } | 231 } |
173 | 232 |
174 // Cairo always returns a valid pointer. | 233 // Cairo always returns a valid pointer. |
175 // Hence, we have to check if it points to a "nil" object. | 234 // Hence, we have to check if it points to a "nil" object. |
176 if (!IsSurfaceValid(page_surface_)) { | 235 if (!IsSurfaceValid(page_surface_)) { |
177 DLOG(ERROR) << "Cannot create Cairo surface for PdfPsMetafile!"; | 236 DLOG(ERROR) << "Cannot create Cairo surface for PdfPsMetafile!"; |
178 CleanUp(); | 237 CleanUpAll(); |
179 return NULL; | 238 return NULL; |
180 } | 239 } |
181 | 240 |
182 // Create a context. | 241 // Creates a context. |
183 page_context_ = cairo_create(page_surface_); | 242 page_context_ = cairo_create(page_surface_); |
184 if (!IsContextValid(page_context_)) { | 243 if (!IsContextValid(page_context_)) { |
185 DLOG(ERROR) << "Cannot create Cairo context for PdfPsMetafile!"; | 244 DLOG(ERROR) << "Cannot create Cairo context for PdfPsMetafile!"; |
186 CleanUp(); | 245 CleanUpAll(); |
187 return NULL; | 246 return NULL; |
188 } | 247 } |
189 | 248 |
190 return page_context_; | 249 return page_context_; |
191 } | 250 } |
192 | 251 |
193 bool PdfPsMetafile::FinishPage(float shrink) { | 252 bool PdfPsMetafile::FinishPage(float shrink) { |
194 DCHECK(IsSurfaceValid(surface_)); | 253 DCHECK(IsSurfaceValid(surface_)); |
195 DCHECK(IsContextValid(context_)); | 254 DCHECK(IsContextValid(context_)); |
196 DCHECK(IsSurfaceValid(page_surface_)); | 255 DCHECK(IsSurfaceValid(page_surface_)); |
197 DCHECK(IsContextValid(page_context_)); | 256 DCHECK(IsContextValid(page_context_)); |
198 DCHECK(shrink > 0); | 257 DCHECK_GT(shrink, 0); |
199 | 258 |
200 // Flush all rendering for current page. | 259 // Flushes all rendering for current page. |
201 cairo_surface_flush(page_surface_); | 260 cairo_surface_flush(page_surface_); |
202 | 261 |
203 // TODO(myhuang): Use real page settings. | 262 // TODO(myhuang): Use real page settings. |
204 // We hard-coded page settings here for testing purpose. | 263 // We hard-coded page settings here for testing purpose. |
205 // The paper size is US Letter (8.5 in. by 11 in.). | 264 // The paper size is US Letter (8.5 in. by 11 in.). |
206 // The default margins are: | 265 // The default margins are: |
207 // Left = 0.25 in. | 266 // Left = 0.25 in. |
208 // Right = 0.25 in. | 267 // Right = 0.25 in. |
209 // Top = 0.25 in. | 268 // Top = 0.25 in. |
210 // Bottom = 0.56 in. | 269 // Bottom = 0.56 in. |
211 const double kDPI = 72.0; // Dots (points) per inch. | 270 const double kDPI = 72.0; // Dots (points) per inch. |
212 const double kWidthInInch = 8.5; | 271 const double kWidthInInch = 8.5; |
213 const double kHeightInInch = 11.0; | 272 const double kHeightInInch = 11.0; |
214 const double kWidthInPoint = kWidthInInch * kDPI; | 273 const double kWidthInPoint = kWidthInInch * kDPI; |
215 const double kHeightInPoint = kHeightInInch * kDPI; | 274 const double kHeightInPoint = kHeightInInch * kDPI; |
216 switch (format_) { | 275 switch (format_) { |
217 case PDF: { | 276 case PDF: { |
218 cairo_pdf_surface_set_size(surface_, kWidthInPoint, kHeightInPoint); | 277 cairo_pdf_surface_set_size(surface_, kWidthInPoint, kHeightInPoint); |
219 } | 278 } |
220 break; | 279 break; |
221 | 280 |
222 case PS: { | 281 case PS: { |
223 cairo_ps_surface_set_size(surface_, kWidthInPoint, kHeightInPoint); | 282 cairo_ps_surface_set_size(surface_, kWidthInPoint, kHeightInPoint); |
224 } | 283 } |
225 break; | 284 break; |
226 | 285 |
227 default: | 286 default: |
228 NOTREACHED(); | 287 NOTREACHED(); |
229 CleanUp(); | 288 CleanUpAll(); |
230 return false; | 289 return false; |
231 } | 290 } |
232 | 291 |
233 // Check if our surface is still valid after resizing. | 292 // Checks if our surface is still valid after resizing. |
234 if (!IsSurfaceValid(surface_)) { | 293 if (!IsSurfaceValid(surface_)) { |
235 DLOG(ERROR) << "Cannot resize Cairo surface for PdfPsMetafile!"; | 294 DLOG(ERROR) << "Cannot resize Cairo surface for PdfPsMetafile!"; |
236 CleanUp(); | 295 CleanUpAll(); |
237 return false; | 296 return false; |
238 } | 297 } |
239 | 298 |
240 // Save context's states. | 299 // Saves context's states. |
241 cairo_save(context_); | 300 cairo_save(context_); |
242 // Copy current page onto the surface of final result. | 301 // Copies current page onto the surface of final result. |
243 // Margins are done by coordinates transformation. | 302 // Margins are done by coordinates transformation. |
244 // Please NOTE that we have to call cairo_scale() before we call | 303 // Please NOTE that we have to call cairo_scale() before we call |
245 // cairo_set_source_surface(). | 304 // cairo_set_source_surface(). |
246 const double scale_factor = 1. / shrink; | 305 const double scale_factor = 1. / shrink; |
247 cairo_scale(context_, scale_factor, scale_factor); | 306 cairo_scale(context_, scale_factor, scale_factor); |
248 const double kLeftMarginInInch = 0.25; | 307 const double kLeftMarginInInch = 0.25; |
249 const double kTopMarginInInch = 0.25; | 308 const double kTopMarginInInch = 0.25; |
250 const double kLeftMarginInPoint = kLeftMarginInInch * kDPI; | 309 const double kLeftMarginInPoint = kLeftMarginInInch * kDPI; |
251 const double kTopMarginInPoint = kTopMarginInInch * kDPI; | 310 const double kTopMarginInPoint = kTopMarginInInch * kDPI; |
252 const double kScaledLeftMarginInPoint = kLeftMarginInPoint * shrink; | 311 const double kScaledLeftMarginInPoint = kLeftMarginInPoint * shrink; |
(...skipping 15 matching lines...) Expand all Loading... |
268 kPrintableWidthInInch * kDPI * shrink; | 327 kPrintableWidthInInch * kDPI * shrink; |
269 const double kScaledPrintableHeightInPoint = | 328 const double kScaledPrintableHeightInPoint = |
270 kPrintableHeightInInch * kDPI * shrink; | 329 kPrintableHeightInInch * kDPI * shrink; |
271 cairo_rectangle(context_, | 330 cairo_rectangle(context_, |
272 kScaledLeftMarginInPoint, | 331 kScaledLeftMarginInPoint, |
273 kScaledTopMarginInPoint, | 332 kScaledTopMarginInPoint, |
274 kScaledPrintableWidthInPoint, | 333 kScaledPrintableWidthInPoint, |
275 kScaledPrintableHeightInPoint); | 334 kScaledPrintableHeightInPoint); |
276 cairo_fill(context_); | 335 cairo_fill(context_); |
277 | 336 |
278 // Finishing the duplication of current page. | 337 // Finishes the duplication of current page. |
279 cairo_show_page(context_); | 338 cairo_show_page(context_); |
280 cairo_surface_flush(surface_); | 339 cairo_surface_flush(surface_); |
281 | 340 |
282 // Destroy resoreces for current page. | 341 // Destroys resources for current page. |
283 CleanUpContext(&page_context_); | 342 CleanUpContext(&page_context_); |
284 CleanUpSurface(&page_surface_); | 343 CleanUpSurface(&page_surface_); |
285 current_page_.clear(); | 344 current_page_.clear(); |
286 | 345 |
287 // Restore context's states. | 346 // Restores context's states. |
288 cairo_restore(context_); | 347 cairo_restore(context_); |
289 | 348 |
290 return true; | 349 return true; |
291 } | 350 } |
292 | 351 |
293 void PdfPsMetafile::Close() { | 352 void PdfPsMetafile::Close() { |
294 DCHECK(IsSurfaceValid(surface_)); | 353 DCHECK(IsSurfaceValid(surface_)); |
295 DCHECK(IsContextValid(context_)); | 354 DCHECK(IsContextValid(context_)); |
296 // Passing this check implies page_surface_ is NULL, and current_page_ is | 355 // Passing this check implies page_surface_ is NULL, and current_page_ is |
297 // empty. | 356 // empty. |
298 DCHECK(!page_context_); | 357 DCHECK(!page_context_); |
299 | 358 |
300 cairo_surface_finish(surface_); | 359 cairo_surface_finish(surface_); |
301 DCHECK(!all_pages_.empty()); // Make sure we did get something. | 360 DCHECK(!all_pages_.empty()); // Make sure we did get something. |
302 | 361 |
303 CleanUpContext(&context_); | 362 CleanUpContext(&context_); |
304 CleanUpSurface(&surface_); | 363 CleanUpSurface(&surface_); |
| 364 CleanUpFonts(); |
| 365 CleanUpFreeType(); |
| 366 } |
| 367 |
| 368 // static |
| 369 bool PdfPsMetafile::SelectFontById(cairo_t* context, uint32_t font_id) { |
| 370 DCHECK(IsContextValid(context)); |
| 371 DCHECK(SkFontHost::ValidFontID(font_id)); |
| 372 DCHECK(g_ft_library); |
| 373 |
| 374 // Checks if we have a cache hit. |
| 375 MapFontId2FontInfo* g_font_cache = Singleton<MapFontId2FontInfo>::get(); |
| 376 DCHECK(g_font_cache); |
| 377 |
| 378 MapFontId2FontInfo::iterator it = g_font_cache->find(font_id); |
| 379 if (it != g_font_cache->end()) { |
| 380 cairo_set_font_face(context, it->second.cairo_face); |
| 381 if (IsContextValid(context)) { |
| 382 return true; |
| 383 } else { |
| 384 NOTREACHED() << "Cannot set font face in Cairo!"; |
| 385 return false; |
| 386 } |
| 387 } |
| 388 |
| 389 // Cache missed. We need to load and create the font. |
| 390 FontInfo new_font_info = {0}; |
| 391 new_font_info.font_stream = SkFontHost::OpenStream(font_id); |
| 392 DCHECK(new_font_info.font_stream); |
| 393 size_t stream_size = new_font_info.font_stream->getLength(); |
| 394 DCHECK(stream_size) << "The Font stream has nothing!"; |
| 395 |
| 396 FT_Error ft_error = FT_New_Memory_Face( |
| 397 g_ft_library, |
| 398 static_cast<FT_Byte*>( |
| 399 const_cast<void*>(new_font_info.font_stream->getMemoryBase())), |
| 400 stream_size, |
| 401 0, |
| 402 &new_font_info.ft_face); |
| 403 |
| 404 if (ft_error) { |
| 405 new_font_info.font_stream->unref(); |
| 406 DLOG(ERROR) << "Cannot create FT_Face!"; |
| 407 SkASSERT(false); |
| 408 return false; |
| 409 } |
| 410 |
| 411 new_font_info.cairo_face = cairo_ft_font_face_create_for_ft_face( |
| 412 new_font_info.ft_face, 0); |
| 413 DCHECK(new_font_info.cairo_face) << "Cannot create font in Cairo!"; |
| 414 |
| 415 // Manage |new_font_info.ft_face|'s life by Cairo. |
| 416 cairo_status_t status = cairo_font_face_set_user_data( |
| 417 new_font_info.cairo_face, |
| 418 &new_font_info.data_key, |
| 419 new_font_info.ft_face, |
| 420 reinterpret_cast<cairo_destroy_func_t>(FT_Done_Face)); |
| 421 |
| 422 if (status != CAIRO_STATUS_SUCCESS) { |
| 423 DLOG(ERROR) << "Cannot set font's user data in Cairo!"; |
| 424 cairo_font_face_destroy(new_font_info.cairo_face); |
| 425 FT_Done_Face(new_font_info.ft_face); |
| 426 new_font_info.font_stream->unref(); |
| 427 SkASSERT(false); |
| 428 return false; |
| 429 } |
| 430 |
| 431 // Inserts |new_font_info| info |g_font_cache|. |
| 432 (*g_font_cache)[font_id] = new_font_info; |
| 433 |
| 434 cairo_set_font_face(context, new_font_info.cairo_face); |
| 435 if (IsContextValid(context)) { |
| 436 return true; |
| 437 } |
| 438 |
| 439 DLOG(ERROR) << "Connot set font face in Cairo!"; |
| 440 return false; |
305 } | 441 } |
306 | 442 |
307 unsigned int PdfPsMetafile::GetDataSize() const { | 443 unsigned int PdfPsMetafile::GetDataSize() const { |
308 // We need to check at least these two members to ensure that either Init() | 444 // We need to check at least these two members to ensure that either Init() |
309 // has been called to initialize |all_pages_|, or metafile has been closed. | 445 // has been called to initialize |all_pages_|, or metafile has been closed. |
310 // Passing these two checks also implies that surface_, page_surface_, and | 446 // Passing these two checks also implies that surface_, page_surface_, and |
311 // page_context_ are NULL, and current_page_ is empty. | 447 // page_context_ are NULL, and current_page_ is empty. |
312 DCHECK(!context_); | 448 DCHECK(!context_); |
313 DCHECK(!all_pages_.empty()); | 449 DCHECK(!all_pages_.empty()); |
314 | 450 |
315 return all_pages_.size(); | 451 return all_pages_.size(); |
316 } | 452 } |
317 | 453 |
318 bool PdfPsMetafile::GetData(void* dst_buffer, size_t dst_buffer_size) const { | 454 bool PdfPsMetafile::GetData(void* dst_buffer, size_t dst_buffer_size) const { |
319 DCHECK(dst_buffer); | 455 DCHECK(dst_buffer); |
320 DCHECK(dst_buffer_size > 0); | 456 DCHECK_GT(dst_buffer_size, 0u); |
321 // We need to check at least these two members to ensure that either Init() | 457 // We need to check at least these two members to ensure that either Init() |
322 // has been called to initialize |all_pages_|, or metafile has been closed. | 458 // has been called to initialize |all_pages_|, or metafile has been closed. |
323 // Passing these two checks also implies that surface_, page_surface_, and | 459 // Passing these two checks also implies that surface_, page_surface_, and |
324 // page_context_ are NULL, and current_page_ is empty. | 460 // page_context_ are NULL, and current_page_ is empty. |
325 DCHECK(!context_); | 461 DCHECK(!context_); |
326 DCHECK(!all_pages_.empty()); | 462 DCHECK(!all_pages_.empty()); |
327 | 463 |
328 size_t data_size = GetDataSize(); | 464 size_t data_size = GetDataSize(); |
329 if (dst_buffer_size > data_size) { | 465 if (dst_buffer_size > data_size) { |
330 return false; | 466 return false; |
(...skipping 16 matching lines...) Expand all Loading... |
347 const unsigned int bytes_written = | 483 const unsigned int bytes_written = |
348 file_util::WriteFile(filename, all_pages_.data(), data_size); | 484 file_util::WriteFile(filename, all_pages_.data(), data_size); |
349 if (bytes_written != data_size) { | 485 if (bytes_written != data_size) { |
350 DLOG(ERROR) << "Failed to save file: " << filename.value(); | 486 DLOG(ERROR) << "Failed to save file: " << filename.value(); |
351 return false; | 487 return false; |
352 } | 488 } |
353 | 489 |
354 return true; | 490 return true; |
355 } | 491 } |
356 | 492 |
357 void PdfPsMetafile::CleanUp() { | 493 void PdfPsMetafile::CleanUpAll() { |
358 CleanUpContext(&context_); | 494 CleanUpContext(&context_); |
359 CleanUpSurface(&surface_); | 495 CleanUpSurface(&surface_); |
360 CleanUpContext(&page_context_); | 496 CleanUpContext(&page_context_); |
361 CleanUpSurface(&page_surface_); | 497 CleanUpSurface(&page_surface_); |
362 current_page_.clear(); | 498 current_page_.clear(); |
363 all_pages_.clear(); | 499 all_pages_.clear(); |
| 500 CleanUpFonts(); |
| 501 CleanUpFreeType(); |
364 } | 502 } |
365 | 503 |
366 } // namespace printing | 504 } // namespace printing |
367 | 505 |
OLD | NEW |