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

Side by Side Diff: core/fxcodec/codec/fx_codec_jpeg.cpp

Issue 2608663003: Pdfium Patch to restore PS Path (Closed)
Patch Set: Created 3 years, 11 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
« no previous file with comments | « core/fxcodec/codec/fx_codec_flate.cpp ('k') | core/fxge/cfx_windowsdevice.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2014 PDFium Authors. All rights reserved. 1 // Copyright 2014 PDFium 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6 6
7 #include <setjmp.h> 7 #include <setjmp.h>
8 8
9 #include <memory> 9 #include <memory>
10 #include <utility> 10 #include <utility>
11 11
12 #include "core/fxcodec/codec/codec_int.h" 12 #include "core/fxcodec/codec/codec_int.h"
13 #include "core/fxcodec/fx_codec.h" 13 #include "core/fxcodec/fx_codec.h"
14 #include "core/fxcrt/fx_safe_types.h" 14 #include "core/fxcrt/fx_safe_types.h"
15 #include "core/fxge/fx_dib.h" 15 #include "core/fxge/fx_dib.h"
16 #include "third_party/base/ptr_util.h" 16 #include "third_party/base/ptr_util.h"
17 17
18 extern "C" { 18 extern "C" {
19 #undef FAR 19 #undef FAR
20 #if defined(USE_SYSTEM_LIBJPEG) 20 #if defined(USE_SYSTEM_LIBJPEG)
21 #include <jpeglib.h> 21 #include <jpeglib.h>
22 #elif defined(USE_LIBJPEG_TURBO) 22 #elif defined(USE_LIBJPEG_TURBO)
23 #include "third_party/libjpeg_turbo/jpeglib.h" 23 #include "third_party/libjpeg_turbo/jpeglib.h"
24 #else 24 #else
25 #include "third_party/libjpeg/jpeglib.h" 25 #include "third_party/libjpeg/jpeglib.h"
26 #endif 26 #endif
27 } 27 }
28 28
29 extern "C" { 29 extern "C" {
30
30 static void JpegScanSOI(const uint8_t** src_buf, uint32_t* src_size) { 31 static void JpegScanSOI(const uint8_t** src_buf, uint32_t* src_size) {
31 if (*src_size == 0) 32 if (*src_size == 0)
32 return; 33 return;
33 34
34 uint32_t offset = 0; 35 uint32_t offset = 0;
35 while (offset < *src_size - 1) { 36 while (offset < *src_size - 1) {
36 if ((*src_buf)[offset] == 0xff && (*src_buf)[offset + 1] == 0xd8) { 37 if ((*src_buf)[offset] == 0xff && (*src_buf)[offset + 1] == 0xd8) {
37 *src_buf += offset; 38 *src_buf += offset;
38 *src_size -= offset; 39 *src_size -= offset;
39 return; 40 return;
40 } 41 }
41 offset++; 42 offset++;
42 } 43 }
43 } 44 }
44 }; 45
45 extern "C" { 46 static void src_do_nothing(struct jpeg_decompress_struct* cinfo) {}
46 static void _src_do_nothing(struct jpeg_decompress_struct* cinfo) {} 47
47 }; 48 static void error_fatal(j_common_ptr cinfo) {
48 extern "C" {
49 static void _error_fatal(j_common_ptr cinfo) {
50 longjmp(*(jmp_buf*)cinfo->client_data, -1); 49 longjmp(*(jmp_buf*)cinfo->client_data, -1);
51 } 50 }
52 }; 51 static void src_skip_data(struct jpeg_decompress_struct* cinfo, long num) {
53 extern "C" {
54 static void _src_skip_data(struct jpeg_decompress_struct* cinfo, long num) {
55 if (num > (long)cinfo->src->bytes_in_buffer) { 52 if (num > (long)cinfo->src->bytes_in_buffer) {
56 _error_fatal((j_common_ptr)cinfo); 53 error_fatal((j_common_ptr)cinfo);
57 } 54 }
58 cinfo->src->next_input_byte += num; 55 cinfo->src->next_input_byte += num;
59 cinfo->src->bytes_in_buffer -= num; 56 cinfo->src->bytes_in_buffer -= num;
60 } 57 }
61 }; 58
62 extern "C" { 59 static boolean src_fill_buffer(j_decompress_ptr cinfo) {
63 static boolean _src_fill_buffer(j_decompress_ptr cinfo) {
64 return 0; 60 return 0;
65 } 61 }
66 }; 62
67 extern "C" { 63 static boolean src_resync(j_decompress_ptr cinfo, int desired) {
68 static boolean _src_resync(j_decompress_ptr cinfo, int desired) {
69 return 0; 64 return 0;
70 } 65 }
71 }; 66
72 extern "C" { 67 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
73 static void _error_do_nothing(j_common_ptr cinfo) {} 68 static void dest_do_nothing(j_compress_ptr cinfo) {}
74 }; 69
75 extern "C" { 70 static boolean dest_empty(j_compress_ptr cinfo) {
76 static void _error_do_nothing1(j_common_ptr cinfo, int) {} 71 return false;
77 }; 72 }
78 extern "C" { 73 #endif
79 static void _error_do_nothing2(j_common_ptr cinfo, char*) {} 74
75 static void error_do_nothing(j_common_ptr cinfo) {}
76
77 static void error_do_nothing1(j_common_ptr cinfo, int) {}
78
79 static void error_do_nothing2(j_common_ptr cinfo, char*) {}
80 }; 80 };
81 81
82 #define JPEG_MARKER_ICC (JPEG_APP0 + 2) 82 #define JPEG_MARKER_ICC (JPEG_APP0 + 2)
83 #define JPEG_MARKER_MAXSIZE 0xFFFF 83 #define JPEG_MARKER_MAXSIZE 0xFFFF
84 84
85 #ifdef PDF_ENABLE_XFA 85 #ifdef PDF_ENABLE_XFA
86 static void JpegLoadAttribute(struct jpeg_decompress_struct* pInfo, 86 static void JpegLoadAttribute(struct jpeg_decompress_struct* pInfo,
87 CFX_DIBAttribute* pAttribute) { 87 CFX_DIBAttribute* pAttribute) {
88 if (!pAttribute) 88 if (!pAttribute)
89 return; 89 return;
90 90
91 pAttribute->m_nXDPI = pInfo->X_density; 91 pAttribute->m_nXDPI = pInfo->X_density;
92 pAttribute->m_nYDPI = pInfo->Y_density; 92 pAttribute->m_nYDPI = pInfo->Y_density;
93 pAttribute->m_wDPIUnit = pInfo->density_unit; 93 pAttribute->m_wDPIUnit = pInfo->density_unit;
94 } 94 }
95 #endif // PDF_ENABLE_XFA 95 #endif // PDF_ENABLE_XFA
96 96
97 static bool JpegLoadInfo(const uint8_t* src_buf, 97 static bool JpegLoadInfo(const uint8_t* src_buf,
98 uint32_t src_size, 98 uint32_t src_size,
99 int* width, 99 int* width,
100 int* height, 100 int* height,
101 int* num_components, 101 int* num_components,
102 int* bits_per_components, 102 int* bits_per_components,
103 bool* color_transform) { 103 bool* color_transform) {
104 JpegScanSOI(&src_buf, &src_size); 104 JpegScanSOI(&src_buf, &src_size);
105 struct jpeg_decompress_struct cinfo; 105 struct jpeg_decompress_struct cinfo;
106 struct jpeg_error_mgr jerr; 106 struct jpeg_error_mgr jerr;
107 jerr.error_exit = _error_fatal; 107 jerr.error_exit = error_fatal;
108 jerr.emit_message = _error_do_nothing1; 108 jerr.emit_message = error_do_nothing1;
109 jerr.output_message = _error_do_nothing; 109 jerr.output_message = error_do_nothing;
110 jerr.format_message = _error_do_nothing2; 110 jerr.format_message = error_do_nothing2;
111 jerr.reset_error_mgr = _error_do_nothing; 111 jerr.reset_error_mgr = error_do_nothing;
112 jerr.trace_level = 0; 112 jerr.trace_level = 0;
113 cinfo.err = &jerr; 113 cinfo.err = &jerr;
114 jmp_buf mark; 114 jmp_buf mark;
115 cinfo.client_data = &mark; 115 cinfo.client_data = &mark;
116 if (setjmp(mark) == -1) 116 if (setjmp(mark) == -1)
117 return false; 117 return false;
118 118
119 jpeg_create_decompress(&cinfo); 119 jpeg_create_decompress(&cinfo);
120 struct jpeg_source_mgr src; 120 struct jpeg_source_mgr src;
121 src.init_source = _src_do_nothing; 121 src.init_source = src_do_nothing;
122 src.term_source = _src_do_nothing; 122 src.term_source = src_do_nothing;
123 src.skip_input_data = _src_skip_data; 123 src.skip_input_data = src_skip_data;
124 src.fill_input_buffer = _src_fill_buffer; 124 src.fill_input_buffer = src_fill_buffer;
125 src.resync_to_restart = _src_resync; 125 src.resync_to_restart = src_resync;
126 src.bytes_in_buffer = src_size; 126 src.bytes_in_buffer = src_size;
127 src.next_input_byte = src_buf; 127 src.next_input_byte = src_buf;
128 cinfo.src = &src; 128 cinfo.src = &src;
129 if (setjmp(mark) == -1) { 129 if (setjmp(mark) == -1) {
130 jpeg_destroy_decompress(&cinfo); 130 jpeg_destroy_decompress(&cinfo);
131 return false; 131 return false;
132 } 132 }
133 int ret = jpeg_read_header(&cinfo, true); 133 int ret = jpeg_read_header(&cinfo, true);
134 if (ret != JPEG_HEADER_OK) { 134 if (ret != JPEG_HEADER_OK) {
135 jpeg_destroy_decompress(&cinfo); 135 jpeg_destroy_decompress(&cinfo);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 234
235 bool CCodec_JpegDecoder::Create(const uint8_t* src_buf, 235 bool CCodec_JpegDecoder::Create(const uint8_t* src_buf,
236 uint32_t src_size, 236 uint32_t src_size,
237 int width, 237 int width,
238 int height, 238 int height,
239 int nComps, 239 int nComps,
240 bool ColorTransform) { 240 bool ColorTransform) {
241 JpegScanSOI(&src_buf, &src_size); 241 JpegScanSOI(&src_buf, &src_size);
242 m_SrcBuf = src_buf; 242 m_SrcBuf = src_buf;
243 m_SrcSize = src_size; 243 m_SrcSize = src_size;
244 jerr.error_exit = _error_fatal; 244 jerr.error_exit = error_fatal;
245 jerr.emit_message = _error_do_nothing1; 245 jerr.emit_message = error_do_nothing1;
246 jerr.output_message = _error_do_nothing; 246 jerr.output_message = error_do_nothing;
247 jerr.format_message = _error_do_nothing2; 247 jerr.format_message = error_do_nothing2;
248 jerr.reset_error_mgr = _error_do_nothing; 248 jerr.reset_error_mgr = error_do_nothing;
249 src.init_source = _src_do_nothing; 249 src.init_source = src_do_nothing;
250 src.term_source = _src_do_nothing; 250 src.term_source = src_do_nothing;
251 src.skip_input_data = _src_skip_data; 251 src.skip_input_data = src_skip_data;
252 src.fill_input_buffer = _src_fill_buffer; 252 src.fill_input_buffer = src_fill_buffer;
253 src.resync_to_restart = _src_resync; 253 src.resync_to_restart = src_resync;
254 m_bJpegTransform = ColorTransform; 254 m_bJpegTransform = ColorTransform;
255 if (src_size > 1 && 255 if (src_size > 1 &&
256 FXSYS_memcmp(src_buf + src_size - 2, "\xFF\xD9", 2) != 0) { 256 FXSYS_memcmp(src_buf + src_size - 2, "\xFF\xD9", 2) != 0) {
257 ((uint8_t*)src_buf)[src_size - 2] = 0xFF; 257 ((uint8_t*)src_buf)[src_size - 2] = 0xFF;
258 ((uint8_t*)src_buf)[src_size - 1] = 0xD9; 258 ((uint8_t*)src_buf)[src_size - 1] = 0xD9;
259 } 259 }
260 m_OutputWidth = m_OrigWidth = width; 260 m_OutputWidth = m_OrigWidth = width;
261 m_OutputHeight = m_OrigHeight = height; 261 m_OutputHeight = m_OrigHeight = height;
262 if (!InitDecode()) 262 if (!InitDecode())
263 return false; 263 return false;
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 struct FXJPEG_Context { 347 struct FXJPEG_Context {
348 jmp_buf m_JumpMark; 348 jmp_buf m_JumpMark;
349 jpeg_decompress_struct m_Info; 349 jpeg_decompress_struct m_Info;
350 jpeg_error_mgr m_ErrMgr; 350 jpeg_error_mgr m_ErrMgr;
351 jpeg_source_mgr m_SrcMgr; 351 jpeg_source_mgr m_SrcMgr;
352 unsigned int m_SkipSize; 352 unsigned int m_SkipSize;
353 void* (*m_AllocFunc)(unsigned int); 353 void* (*m_AllocFunc)(unsigned int);
354 void (*m_FreeFunc)(void*); 354 void (*m_FreeFunc)(void*);
355 }; 355 };
356 extern "C" { 356 extern "C" {
357 static void _error_fatal1(j_common_ptr cinfo) { 357 static void error_fatal1(j_common_ptr cinfo) {
358 longjmp(((FXJPEG_Context*)cinfo->client_data)->m_JumpMark, -1); 358 longjmp(((FXJPEG_Context*)cinfo->client_data)->m_JumpMark, -1);
359 } 359 }
360 }; 360 };
361 extern "C" { 361 extern "C" {
362 static void _src_skip_data1(struct jpeg_decompress_struct* cinfo, long num) { 362 static void src_skip_data1(struct jpeg_decompress_struct* cinfo, long num) {
363 if (cinfo->src->bytes_in_buffer < (size_t)num) { 363 if (cinfo->src->bytes_in_buffer < (size_t)num) {
364 ((FXJPEG_Context*)cinfo->client_data)->m_SkipSize = 364 ((FXJPEG_Context*)cinfo->client_data)->m_SkipSize =
365 (unsigned int)(num - cinfo->src->bytes_in_buffer); 365 (unsigned int)(num - cinfo->src->bytes_in_buffer);
366 cinfo->src->bytes_in_buffer = 0; 366 cinfo->src->bytes_in_buffer = 0;
367 } else { 367 } else {
368 cinfo->src->next_input_byte += num; 368 cinfo->src->next_input_byte += num;
369 cinfo->src->bytes_in_buffer -= num; 369 cinfo->src->bytes_in_buffer -= num;
370 } 370 }
371 } 371 }
372 }; 372 };
373 static void* jpeg_alloc_func(unsigned int size) { 373 static void* jpeg_alloc_func(unsigned int size) {
374 return FX_Alloc(char, size); 374 return FX_Alloc(char, size);
375 } 375 }
376 static void jpeg_free_func(void* p) { 376 static void jpeg_free_func(void* p) {
377 FX_Free(p); 377 FX_Free(p);
378 } 378 }
379 FXJPEG_Context* CCodec_JpegModule::Start() { 379 FXJPEG_Context* CCodec_JpegModule::Start() {
380 FXJPEG_Context* p = FX_Alloc(FXJPEG_Context, 1); 380 FXJPEG_Context* p = FX_Alloc(FXJPEG_Context, 1);
381 p->m_AllocFunc = jpeg_alloc_func; 381 p->m_AllocFunc = jpeg_alloc_func;
382 p->m_FreeFunc = jpeg_free_func; 382 p->m_FreeFunc = jpeg_free_func;
383 p->m_ErrMgr.error_exit = _error_fatal1; 383 p->m_ErrMgr.error_exit = error_fatal1;
384 p->m_ErrMgr.emit_message = _error_do_nothing1; 384 p->m_ErrMgr.emit_message = error_do_nothing1;
385 p->m_ErrMgr.output_message = _error_do_nothing; 385 p->m_ErrMgr.output_message = error_do_nothing;
386 p->m_ErrMgr.format_message = _error_do_nothing2; 386 p->m_ErrMgr.format_message = error_do_nothing2;
387 p->m_ErrMgr.reset_error_mgr = _error_do_nothing; 387 p->m_ErrMgr.reset_error_mgr = error_do_nothing;
388 p->m_SrcMgr.init_source = _src_do_nothing; 388 p->m_SrcMgr.init_source = src_do_nothing;
389 p->m_SrcMgr.term_source = _src_do_nothing; 389 p->m_SrcMgr.term_source = src_do_nothing;
390 p->m_SrcMgr.skip_input_data = _src_skip_data1; 390 p->m_SrcMgr.skip_input_data = src_skip_data1;
391 p->m_SrcMgr.fill_input_buffer = _src_fill_buffer; 391 p->m_SrcMgr.fill_input_buffer = src_fill_buffer;
392 p->m_SrcMgr.resync_to_restart = _src_resync; 392 p->m_SrcMgr.resync_to_restart = src_resync;
393 p->m_Info.client_data = p; 393 p->m_Info.client_data = p;
394 p->m_Info.err = &p->m_ErrMgr; 394 p->m_Info.err = &p->m_ErrMgr;
395 if (setjmp(p->m_JumpMark) == -1) { 395 if (setjmp(p->m_JumpMark) == -1) {
396 return 0; 396 return 0;
397 } 397 }
398 jpeg_create_decompress(&p->m_Info); 398 jpeg_create_decompress(&p->m_Info);
399 p->m_Info.src = &p->m_SrcMgr; 399 p->m_Info.src = &p->m_SrcMgr;
400 p->m_SkipSize = 0; 400 p->m_SkipSize = 0;
401 return p; 401 return p;
402 } 402 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 uint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx, 473 uint32_t CCodec_JpegModule::GetAvailInput(FXJPEG_Context* ctx,
474 uint8_t** avail_buf_ptr) { 474 uint8_t** avail_buf_ptr) {
475 if (avail_buf_ptr) { 475 if (avail_buf_ptr) {
476 *avail_buf_ptr = nullptr; 476 *avail_buf_ptr = nullptr;
477 if (ctx->m_SrcMgr.bytes_in_buffer > 0) { 477 if (ctx->m_SrcMgr.bytes_in_buffer > 0) {
478 *avail_buf_ptr = (uint8_t*)ctx->m_SrcMgr.next_input_byte; 478 *avail_buf_ptr = (uint8_t*)ctx->m_SrcMgr.next_input_byte;
479 } 479 }
480 } 480 }
481 return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer; 481 return (uint32_t)ctx->m_SrcMgr.bytes_in_buffer;
482 } 482 }
483
484 #if _FX_OS_ == _FX_WIN32_DESKTOP_ || _FX_OS_ == _FX_WIN64_DESKTOP_
485 // static
486 bool CCodec_JpegModule::JpegEncode(const CFX_DIBSource* pSource,
487 uint8_t*& dest_buf,
488 FX_STRSIZE& dest_size) {
489 if (pSource->GetBPP() < 8 || pSource->GetPalette())
490 return false;
491
492 struct jpeg_error_mgr jerr;
493 jerr.error_exit = error_do_nothing;
494 jerr.emit_message = error_do_nothing1;
495 jerr.output_message = error_do_nothing;
496 jerr.format_message = error_do_nothing2;
497 jerr.reset_error_mgr = error_do_nothing;
498
499 struct jpeg_compress_struct cinfo;
500 memset(&cinfo, 0, sizeof(cinfo));
501 cinfo.err = &jerr;
502 jpeg_create_compress(&cinfo);
503 int bpp = pSource->GetBPP() / 8;
504 uint32_t nComponents = bpp >= 3 ? (pSource->IsCmykImage() ? 4 : 3) : 1;
505 uint32_t pitch = pSource->GetPitch();
506 uint32_t width = pdfium::base::checked_cast<uint32_t>(pSource->GetWidth());
507 uint32_t height = pdfium::base::checked_cast<uint32_t>(pSource->GetHeight());
508 FX_SAFE_UINT32 safe_buf_len = width;
509 safe_buf_len *= height;
510 safe_buf_len *= nComponents;
511 safe_buf_len += 1024;
512 if (!safe_buf_len.IsValid())
513 return false;
514
515 uint32_t dest_buf_length = safe_buf_len.ValueOrDie();
516 dest_buf = FX_TryAlloc(uint8_t, dest_buf_length);
517 const int MIN_TRY_BUF_LEN = 1024;
518 while (!dest_buf && dest_buf_length > MIN_TRY_BUF_LEN) {
519 dest_buf_length >>= 1;
520 dest_buf = FX_TryAlloc(uint8_t, dest_buf_length);
521 }
522 if (!dest_buf)
523 return false;
524
525 struct jpeg_destination_mgr dest;
526 dest.init_destination = dest_do_nothing;
527 dest.term_destination = dest_do_nothing;
528 dest.empty_output_buffer = dest_empty;
529 dest.next_output_byte = dest_buf;
530 dest.free_in_buffer = dest_buf_length;
531 cinfo.dest = &dest;
532 cinfo.image_width = width;
533 cinfo.image_height = height;
534 cinfo.input_components = nComponents;
535 if (nComponents == 1)
536 cinfo.in_color_space = JCS_GRAYSCALE;
537 else if (nComponents == 3)
538 cinfo.in_color_space = JCS_RGB;
539 else
540 cinfo.in_color_space = JCS_CMYK;
541
542 uint8_t* line_buf = nullptr;
543 if (nComponents > 1)
544 line_buf = FX_Alloc2D(uint8_t, width, nComponents);
545
546 jpeg_set_defaults(&cinfo);
547 jpeg_start_compress(&cinfo, TRUE);
548 JSAMPROW row_pointer[1];
549 JDIMENSION row;
550 while (cinfo.next_scanline < cinfo.image_height) {
551 const uint8_t* src_scan = pSource->GetScanline(cinfo.next_scanline);
552 if (nComponents > 1) {
553 uint8_t* dest_scan = line_buf;
554 if (nComponents == 3) {
555 for (uint32_t i = 0; i < width; i++) {
556 dest_scan[0] = src_scan[2];
557 dest_scan[1] = src_scan[1];
558 dest_scan[2] = src_scan[0];
559 dest_scan += 3;
560 src_scan += bpp;
561 }
562 } else {
563 for (uint32_t i = 0; i < pitch; i++) {
564 *dest_scan++ = ~*src_scan++;
565 }
566 }
567 row_pointer[0] = line_buf;
568 } else {
569 row_pointer[0] = (uint8_t*)src_scan;
570 }
571 row = cinfo.next_scanline;
572 jpeg_write_scanlines(&cinfo, row_pointer, 1);
573 if (cinfo.next_scanline == row) {
574 static const uint32_t kJpegBlockSize = 1048576;
575 dest_buf =
576 FX_Realloc(uint8_t, dest_buf, dest_buf_length + kJpegBlockSize);
577 dest.next_output_byte = dest_buf + dest_buf_length - dest.free_in_buffer;
578 dest_buf_length += kJpegBlockSize;
579 dest.free_in_buffer += kJpegBlockSize;
580 }
581 }
582 jpeg_finish_compress(&cinfo);
583 jpeg_destroy_compress(&cinfo);
584 FX_Free(line_buf);
585 dest_size = dest_buf_length - (FX_STRSIZE)dest.free_in_buffer;
586
587 return true;
588 }
589 #endif
OLDNEW
« no previous file with comments | « core/fxcodec/codec/fx_codec_flate.cpp ('k') | core/fxge/cfx_windowsdevice.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698