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

Side by Side Diff: core/fxge/win32/fx_ge_ps.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/fxge/win32/fx_ge_ps.h ('k') | core/fxge/win32/fx_win32_device.cpp » ('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 2014 PDFium 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include <memory>
8
9 #include "core/fpdfapi/cpdf_modulemgr.h"
10 #include "core/fxcodec/fx_codec.h"
11 #include "core/fxcrt/cfx_maybe_owned.h"
12 #include "core/fxge/cfx_facecache.h"
13 #include "core/fxge/cfx_fontcache.h"
14 #include "core/fxge/cfx_pathdata.h"
15 #include "core/fxge/cfx_renderdevice.h"
16 #include "core/fxge/ge/fx_text_int.h"
17 #include "core/fxge/win32/fx_ge_ps.h"
18
19 namespace {
20
21 void FaxCompressData(uint8_t* src_buf,
22 int width,
23 int height,
24 std::unique_ptr<uint8_t, FxFreeDeleter>& dest_buf,
25 uint32_t& dest_size) {
26 if (width * height > 128) {
27 CCodec_FaxModule::FaxEncode(src_buf, width, height, (width + 7) / 8,
28 dest_buf, dest_size);
29 FX_Free(src_buf);
30 } else {
31 dest_buf.reset(src_buf);
32 dest_size = (width + 7) / 8 * height;
33 }
34 }
35
36 void PSCompressData(int PSLevel,
37 uint8_t* src_buf,
38 uint32_t src_size,
39 uint8_t*& output_buf,
40 uint32_t& output_size,
41 const FX_CHAR*& filter) {
42 printf("PS Compress Data Level %d\n", PSLevel);
43 output_buf = src_buf;
44 output_size = src_size;
45 filter = "";
46 if (src_size < 1024)
47 return;
48 CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule();
49 uint8_t* dest_buf = nullptr;
50 uint32_t dest_size = src_size;
51 if (PSLevel >= 3) {
52 if (pEncoders &&
53 pEncoders->GetFlateModule()->Encode(src_buf, src_size, &dest_buf,
54 &dest_size)) {
55 filter = "/FlateDecode filter ";
56 }
57 } else {
58 if (pEncoders &&
59 pEncoders->GetBasicModule()->RunLengthEncode(src_buf, src_size,
60 dest_buf, dest_size)) {
61 filter = "/RunLengthDecode filter ";
62 }
63 }
64 if (dest_size < src_size) {
65 output_buf = dest_buf;
66 output_size = dest_size;
67 } else {
68 filter = nullptr;
69 FX_Free(dest_buf);
70 }
71 }
72
73 } // namespace
74
75 struct PSGlyph {
76 CFX_Font* m_pFont;
77 uint32_t m_GlyphIndex;
78 bool m_bGlyphAdjust;
79 FX_FLOAT m_AdjustMatrix[4];
80 };
81
82 class CPSFont {
83 public:
84 PSGlyph m_Glyphs[256];
85 int m_nGlyphs;
86 };
87
88 CFX_PSRenderer::CFX_PSRenderer() {
89 m_pOutput = nullptr;
90 m_bColorSet = m_bGraphStateSet = false;
91 m_bInited = false;
92 }
93
94 CFX_PSRenderer::~CFX_PSRenderer() {
95 for (int i = 0; i < (int)m_PSFontList.GetSize(); i++) {
96 CPSFont* pFont = m_PSFontList[i];
97 delete pFont;
98 }
99 }
100
101 #define OUTPUT_PS(str) m_pOutput->OutputPS(str, sizeof(str) - 1)
102
103 void CFX_PSRenderer::Init(IFX_PSOutput* pOutput,
104 int pslevel,
105 int width,
106 int height,
107 bool bCmykOutput) {
108 m_PSLevel = pslevel;
109 m_pOutput = pOutput;
110 m_ClipBox.left = m_ClipBox.top = 0;
111 m_ClipBox.right = width;
112 m_ClipBox.bottom = height;
113 m_bCmykOutput = bCmykOutput;
114 }
115
116 bool CFX_PSRenderer::StartRendering() {
117 if (m_bInited)
118 return true;
119
120 static const char init_str[] =
121 "\nsave\n/im/initmatrix load def\n"
122 "/n/newpath load def/m/moveto load def/l/lineto load def/c/curveto load "
123 "def/h/closepath load def\n"
124 "/f/fill load def/F/eofill load def/s/stroke load def/W/clip load "
125 "def/W*/eoclip load def\n"
126 "/rg/setrgbcolor load def/k/setcmykcolor load def\n"
127 "/J/setlinecap load def/j/setlinejoin load def/w/setlinewidth load "
128 "def/M/setmiterlimit load def/d/setdash load def\n"
129 "/q/gsave load def/Q/grestore load def/iM/imagemask load def\n"
130 "/Tj/show load def/Ff/findfont load def/Fs/scalefont load def/Sf/setfont "
131 "load def\n"
132 "/cm/concat load def/Cm/currentmatrix load def/mx/matrix load "
133 "def/sm/setmatrix load def\n";
134 OUTPUT_PS(init_str);
135 m_bInited = true;
136 return true;
137 }
138
139 void CFX_PSRenderer::EndRendering() {
140 if (m_bInited)
141 OUTPUT_PS("\nrestore\n");
142 m_bInited = false;
143 }
144 void CFX_PSRenderer::SaveState() {
145 StartRendering();
146 OUTPUT_PS("q\n");
147 m_ClipBoxStack.Add(m_ClipBox);
148 }
149
150 void CFX_PSRenderer::RestoreState(bool bKeepSaved) {
151 StartRendering();
152 if (bKeepSaved)
153 OUTPUT_PS("Q\nq\n");
154 else
155 OUTPUT_PS("Q\n");
156
157 m_bColorSet = false;
158 m_bGraphStateSet = false;
159 int size = m_ClipBoxStack.GetSize();
160 if (!size)
161 return;
162
163 m_ClipBox = m_ClipBoxStack.GetAt(size - 1);
164 if (!bKeepSaved)
165 m_ClipBoxStack.RemoveAt(size - 1);
166 }
167
168 void CFX_PSRenderer::OutputPath(const CFX_PathData* pPathData,
169 const CFX_Matrix* pObject2Device) {
170 int nPoints = pPathData->GetPointCount();
171 CFX_ByteTextBuf buf;
172 buf.EstimateSize(nPoints * 10);
173 for (int i = 0; i < nPoints; i++) {
174 uint8_t flag = pPathData->GetFlag(i);
175 FX_FLOAT x = pPathData->GetPointX(i);
176 FX_FLOAT y = pPathData->GetPointY(i);
177 if (pObject2Device)
178 pObject2Device->Transform(x, y);
179
180 buf << x << " " << y;
181 switch (flag & FXPT_TYPE) {
182 case FXPT_MOVETO:
183 buf << " m ";
184 break;
185 case FXPT_LINETO:
186 buf << " l ";
187 if (flag & FXPT_CLOSEFIGURE)
188 buf << "h ";
189 break;
190 case FXPT_BEZIERTO: {
191 FX_FLOAT x1 = pPathData->GetPointX(i + 1);
192 FX_FLOAT x2 = pPathData->GetPointX(i + 2);
193 FX_FLOAT y1 = pPathData->GetPointY(i + 1);
194 FX_FLOAT y2 = pPathData->GetPointY(i + 2);
195 if (pObject2Device) {
196 pObject2Device->Transform(x1, y1);
197 pObject2Device->Transform(x2, y2);
198 }
199 buf << " " << x1 << " " << y1 << " " << x2 << " " << y2 << " c";
200 if (flag & FXPT_CLOSEFIGURE)
201 buf << " h";
202 buf << "\n";
203 i += 2;
204 break;
205 }
206 }
207 }
208 m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize());
209 }
210
211 void CFX_PSRenderer::SetClip_PathFill(const CFX_PathData* pPathData,
212 const CFX_Matrix* pObject2Device,
213 int fill_mode) {
214 StartRendering();
215 OutputPath(pPathData, pObject2Device);
216 CFX_FloatRect rect = pPathData->GetBoundingBox();
217 fflush(stdout);
218 if (pObject2Device)
219 rect.Transform(pObject2Device);
220 /* This seems to result in the clip box being set to the screen coordinates,
221 * which is wrong.*/
222 /* if (m_ClipBox.left != 0 || m_ClipBox.top != 0)
223 m_ClipBox.Intersect(rect.GetOuterRect());
224 else {*/
225 m_ClipBox.left = static_cast<int>(rect.left);
226 m_ClipBox.right = static_cast<int>(rect.left + rect.right);
227 m_ClipBox.top = static_cast<int>(rect.top + rect.bottom);
228 m_ClipBox.bottom = static_cast<int>(rect.bottom);
229 // }
230 fflush(stdout);
231 if ((fill_mode & 3) == FXFILL_WINDING)
232 OUTPUT_PS("W n\n");
233 else
234 OUTPUT_PS("W* n\n");
235 }
236
237 void CFX_PSRenderer::SetClip_PathStroke(const CFX_PathData* pPathData,
238 const CFX_Matrix* pObject2Device,
239 const CFX_GraphStateData* pGraphState) {
240 StartRendering();
241 SetGraphState(pGraphState);
242 if (pObject2Device) {
243 CFX_ByteTextBuf buf;
244 buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " "
245 << pObject2Device->c << " " << pObject2Device->d << " "
246 << pObject2Device->e << " " << pObject2Device->f << "]cm ";
247 m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize());
248 }
249 OutputPath(pPathData, nullptr);
250 CFX_FloatRect rect = pPathData->GetBoundingBox(pGraphState->m_LineWidth,
251 pGraphState->m_MiterLimit);
252 rect.Transform(pObject2Device);
253 m_ClipBox.Intersect(rect.GetOuterRect());
254 if (pObject2Device)
255 OUTPUT_PS("strokepath W n sm\n");
256 else
257 OUTPUT_PS("strokepath W n\n");
258 }
259
260 bool CFX_PSRenderer::DrawPath(const CFX_PathData* pPathData,
261 const CFX_Matrix* pObject2Device,
262 const CFX_GraphStateData* pGraphState,
263 uint32_t fill_color,
264 uint32_t stroke_color,
265 int fill_mode) {
266 StartRendering();
267 int fill_alpha = FXARGB_A(fill_color);
268 if (fill_alpha && fill_alpha < 255)
269 return false;
270
271 int stroke_alpha = FXARGB_A(stroke_color);
272 if (stroke_alpha && stroke_alpha < 255)
273 return false;
274
275 if (fill_alpha == 0 && stroke_alpha == 0)
276 return false;
277
278 if (stroke_alpha) {
279 SetGraphState(pGraphState);
280 if (pObject2Device) {
281 CFX_ByteTextBuf buf;
282 buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " "
283 << pObject2Device->c << " " << pObject2Device->d << " "
284 << pObject2Device->e << " " << pObject2Device->f << "]cm ";
285 m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize());
286 }
287 }
288 OutputPath(pPathData, stroke_alpha ? nullptr : pObject2Device);
289 if (fill_mode && fill_alpha) {
290 SetColor(fill_color);
291 if ((fill_mode & 3) == FXFILL_WINDING) {
292 if (stroke_alpha)
293 OUTPUT_PS("q f Q ");
294 else
295 OUTPUT_PS("f");
296 } else if ((fill_mode & 3) == FXFILL_ALTERNATE) {
297 if (stroke_alpha)
298 OUTPUT_PS("q F Q ");
299 else
300 OUTPUT_PS("F");
301 }
302 }
303 if (stroke_alpha) {
304 SetColor(stroke_color);
305 if (pObject2Device)
306 OUTPUT_PS("s sm");
307 else
308 OUTPUT_PS("s");
309 }
310 OUTPUT_PS("\n");
311 return true;
312 }
313
314 void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) {
315 CFX_ByteTextBuf buf;
316 if (!m_bGraphStateSet ||
317 m_CurGraphState.m_LineCap != pGraphState->m_LineCap) {
318 buf << pGraphState->m_LineCap << " J\n";
319 }
320 if (!m_bGraphStateSet ||
321 m_CurGraphState.m_DashCount != pGraphState->m_DashCount ||
322 FXSYS_memcmp(m_CurGraphState.m_DashArray, pGraphState->m_DashArray,
323 sizeof(FX_FLOAT) * m_CurGraphState.m_DashCount)) {
324 buf << "[";
325 for (int i = 0; i < pGraphState->m_DashCount; ++i)
326 buf << pGraphState->m_DashArray[i] << " ";
327 buf << "]" << pGraphState->m_DashPhase << " d\n";
328 }
329 if (!m_bGraphStateSet ||
330 m_CurGraphState.m_LineJoin != pGraphState->m_LineJoin) {
331 buf << pGraphState->m_LineJoin << " j\n";
332 }
333 if (!m_bGraphStateSet ||
334 m_CurGraphState.m_LineWidth != pGraphState->m_LineWidth) {
335 buf << pGraphState->m_LineWidth << " w\n";
336 }
337 if (!m_bGraphStateSet ||
338 m_CurGraphState.m_MiterLimit != pGraphState->m_MiterLimit) {
339 buf << pGraphState->m_MiterLimit << " M\n";
340 }
341 m_CurGraphState.Copy(*pGraphState);
342 m_bGraphStateSet = true;
343 if (buf.GetSize()) {
344 m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize());
345 }
346 }
347
348 bool CFX_PSRenderer::SetDIBits(const CFX_DIBSource* pSource,
349 uint32_t color,
350 int left,
351 int top) {
352 StartRendering();
353 CFX_Matrix matrix((FX_FLOAT)(pSource->GetWidth()), 0.0f, 0.0f,
354 -(FX_FLOAT)(pSource->GetHeight()), (FX_FLOAT)(left),
355 (FX_FLOAT)(top + pSource->GetHeight()));
356 return DrawDIBits(pSource, color, &matrix, 0);
357 }
358
359 bool CFX_PSRenderer::StretchDIBits(const CFX_DIBSource* pSource,
360 uint32_t color,
361 int dest_left,
362 int dest_top,
363 int dest_width,
364 int dest_height,
365 uint32_t flags) {
366 StartRendering();
367 CFX_Matrix matrix((FX_FLOAT)(dest_width), 0.0f, 0.0f,
368 (FX_FLOAT)(-dest_height), (FX_FLOAT)(dest_left),
369 (FX_FLOAT)(dest_top + dest_height));
370 return DrawDIBits(pSource, color, &matrix, flags);
371 }
372
373 bool CFX_PSRenderer::DrawDIBits(const CFX_DIBSource* pSource,
374 uint32_t color,
375 const CFX_Matrix* pMatrix,
376 uint32_t flags) {
377 StartRendering();
378 if ((pMatrix->a == 0 && pMatrix->b == 0) ||
379 (pMatrix->c == 0 && pMatrix->d == 0)) {
380 return true;
381 }
382 if (pSource->HasAlpha())
383 return false;
384
385 int alpha = FXARGB_A(color);
386 if (pSource->IsAlphaMask() && (alpha < 255 || pSource->GetBPP() != 1))
387 return false;
388
389 OUTPUT_PS("q\n");
390 CFX_ByteTextBuf buf;
391 buf << "[" << pMatrix->a << " " << pMatrix->b << " " << pMatrix->c << " "
392 << pMatrix->d << " " << pMatrix->e << " " << pMatrix->f << "]cm ";
393 int width = pSource->GetWidth();
394 int height = pSource->GetHeight();
395 buf << width << " " << height;
396 if (pSource->GetBPP() == 1 && !pSource->GetPalette()) {
397 // base::debug::StackTrace().Print(); fflush(stderr); fflush(stdout);
398 int pitch = (width + 7) / 8;
399 uint32_t src_size = height * pitch;
400 uint8_t* src_buf = FX_Alloc(uint8_t, src_size);
401 for (int row = 0; row < height; row++) {
402 const uint8_t* src_scan = pSource->GetScanline(row);
403 FXSYS_memcpy(src_buf + row * pitch, src_scan, pitch);
404 }
405 std::unique_ptr<uint8_t, FxFreeDeleter> output_buf;
406 uint32_t output_size;
407 FaxCompressData(src_buf, width, height, output_buf, output_size);
408 if (pSource->IsAlphaMask()) {
409 SetColor(color);
410 m_bColorSet = false;
411 buf << " true[";
412 } else {
413 buf << " 1[";
414 }
415 buf << width << " 0 0 -" << height << " 0 " << height
416 << "]currentfile/ASCII85Decode filter ";
417 if (output_buf.get() != src_buf) {
418 buf << "<</K -1/EndOfBlock false/Columns " << width << "/Rows " << height
419 << ">>/CCITTFaxDecode filter ";
420 }
421 if (pSource->IsAlphaMask())
422 buf << "iM\n";
423 else
424 buf << "false 1 colorimage\n";
425
426 m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize());
427 WritePSBinary(output_buf.get(), output_size);
428 output_buf.release();
429 } else {
430 // CFX_DIBSource* pConverted = (CFX_DIBSource*)pSource;
431 CFX_MaybeOwned<CFX_DIBSource> pConverted((CFX_DIBSource*)pSource);
432 switch (pSource->GetFormat()) {
433 case FXDIB_1bppRgb:
434 case FXDIB_Rgb32:
435 pConverted = pSource->CloneConvert(FXDIB_Rgb);
436 break;
437 case FXDIB_8bppRgb:
438 if (pSource->GetPalette()) {
439 pConverted = pSource->CloneConvert(FXDIB_Rgb);
440 }
441 break;
442 case FXDIB_1bppCmyk:
443 pConverted = pSource->CloneConvert(FXDIB_Cmyk);
444 break;
445 case FXDIB_8bppCmyk:
446 if (pSource->GetPalette()) {
447 pConverted = pSource->CloneConvert(FXDIB_Cmyk);
448 }
449 break;
450 default:
451 break;
452 }
453 if (!pConverted) {
454 OUTPUT_PS("\nQ\n");
455 return false;
456 }
457 int bpp = pConverted->GetBPP() / 8;
458 uint8_t* output_buf = nullptr;
459 FX_STRSIZE output_size = 0;
460 const FX_CHAR* filter = nullptr;
461 if ((flags & FXRENDER_IMAGE_LOSSY) &&
462 CCodec_JpegModule::JpegEncode(pConverted.Get(), output_buf,
463 output_size)) {
464 filter = "/DCTDecode filter ";
465 }
466 if (!filter) {
467 int src_pitch = width * bpp;
468 output_size = height * src_pitch;
469 output_buf = FX_Alloc(uint8_t, output_size);
470 for (int row = 0; row < height; row++) {
471 const uint8_t* src_scan = pConverted->GetScanline(row);
472 uint8_t* dest_scan = output_buf + row * src_pitch;
473 if (bpp == 3) {
474 for (int col = 0; col < width; col++) {
475 *dest_scan++ = src_scan[2];
476 *dest_scan++ = src_scan[1];
477 *dest_scan++ = *src_scan;
478 src_scan += 3;
479 }
480 } else {
481 FXSYS_memcpy(dest_scan, src_scan, src_pitch);
482 }
483 }
484 uint8_t* compressed_buf;
485 uint32_t compressed_size;
486 PSCompressData(m_PSLevel, output_buf, output_size, compressed_buf,
487 compressed_size, filter);
488 if (output_buf != compressed_buf)
489 FX_Free(output_buf);
490
491 output_buf = compressed_buf;
492 output_size = compressed_size;
493 }
494 CFX_DIBSource* converted = pConverted.Get();
495 if (converted != pSource) {
496 FX_Free(converted);
497 pConverted.Reset();
498 }
499 buf << " 8[";
500 buf << width << " 0 0 -" << height << " 0 " << height << "]";
501 buf << "currentfile/ASCII85Decode filter ";
502 if (filter)
503 buf << filter;
504 buf << "false " << bpp;
505 buf << " colorimage\n";
506 m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize());
507 WritePSBinary(output_buf, output_size);
508 FX_Free(output_buf);
509 }
510 OUTPUT_PS("\nQ\n");
511 return true;
512 }
513
514 void CFX_PSRenderer::SetColor(uint32_t color) {
515 // TODO(thestig): Simplify more?
516 bool bCMYK = false;
517 if (bCMYK != m_bCmykOutput || !m_bColorSet || m_LastColor != color) {
518 CFX_ByteTextBuf buf;
519 if (bCMYK) {
520 buf << FXSYS_GetCValue(color) / 255.0 << " "
521 << FXSYS_GetMValue(color) / 255.0 << " "
522 << FXSYS_GetYValue(color) / 255.0 << " "
523 << FXSYS_GetKValue(color) / 255.0 << " k\n";
524 } else {
525 buf << FXARGB_R(color) / 255.0 << " " << FXARGB_G(color) / 255.0 << " "
526 << FXARGB_B(color) / 255.0 << " rg\n";
527 }
528 if (bCMYK == m_bCmykOutput) {
529 m_bColorSet = true;
530 m_LastColor = color;
531 }
532 m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize());
533 }
534 }
535
536 void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache,
537 CFX_Font* pFont,
538 const FXTEXT_CHARPOS& charpos,
539 int& ps_fontnum,
540 int& ps_glyphindex) {
541 for (int i = 0; i < (int)m_PSFontList.GetSize(); i++) {
542 CPSFont* pPSFont = m_PSFontList[i];
543 for (int j = 0; j < pPSFont->m_nGlyphs; j++)
544 if (pPSFont->m_Glyphs[j].m_pFont == pFont &&
545 pPSFont->m_Glyphs[j].m_GlyphIndex == charpos.m_GlyphIndex) {
546 if ((!pPSFont->m_Glyphs[j].m_bGlyphAdjust && !charpos.m_bGlyphAdjust) ||
547 (pPSFont->m_Glyphs[j].m_bGlyphAdjust && charpos.m_bGlyphAdjust &&
548 (FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[0] -
549 charpos.m_AdjustMatrix[0]) < 0.01 &&
550 FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[1] -
551 charpos.m_AdjustMatrix[1]) < 0.01 &&
552 FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[2] -
553 charpos.m_AdjustMatrix[2]) < 0.01 &&
554 FXSYS_fabs(pPSFont->m_Glyphs[j].m_AdjustMatrix[3] -
555 charpos.m_AdjustMatrix[3]) < 0.01))) {
556 ps_fontnum = i;
557 ps_glyphindex = j;
558 return;
559 }
560 }
561 }
562 if (m_PSFontList.GetSize() == 0 ||
563 m_PSFontList[m_PSFontList.GetSize() - 1]->m_nGlyphs == 256) {
564 CPSFont* pPSFont = new CPSFont;
565 pPSFont->m_nGlyphs = 0;
566 m_PSFontList.Add(pPSFont);
567 CFX_ByteTextBuf buf;
568 buf << "8 dict begin/FontType 3 def/FontMatrix[1 0 0 1 0 0]def\n"
569 "/FontBBox[0 0 0 0]def/Encoding 256 array def 0 1 255{Encoding "
570 "exch/.notdef put}for\n"
571 "/CharProcs 1 dict def CharProcs begin/.notdef {} def end\n"
572 "/BuildGlyph{1 0 -10 -10 10 10 setcachedevice exch/CharProcs get "
573 "exch 2 copy known not{pop/.notdef}if get exec}bind def\n"
574 "/BuildChar{1 index/Encoding get exch get 1 index/BuildGlyph get "
575 "exec}bind def\n"
576 "currentdict end\n";
577 buf << "/X" << m_PSFontList.GetSize() - 1 << " exch definefont pop\n";
578 m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize());
579 buf.Clear();
580 }
581 ps_fontnum = m_PSFontList.GetSize() - 1;
582 CPSFont* pPSFont = m_PSFontList[ps_fontnum];
583 ps_glyphindex = pPSFont->m_nGlyphs;
584 pPSFont->m_Glyphs[ps_glyphindex].m_GlyphIndex = charpos.m_GlyphIndex;
585 pPSFont->m_Glyphs[ps_glyphindex].m_pFont = pFont;
586 pPSFont->m_Glyphs[ps_glyphindex].m_bGlyphAdjust = charpos.m_bGlyphAdjust;
587 if (charpos.m_bGlyphAdjust) {
588 pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[0] =
589 charpos.m_AdjustMatrix[0];
590 pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[1] =
591 charpos.m_AdjustMatrix[1];
592 pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[2] =
593 charpos.m_AdjustMatrix[2];
594 pPSFont->m_Glyphs[ps_glyphindex].m_AdjustMatrix[3] =
595 charpos.m_AdjustMatrix[3];
596 }
597 pPSFont->m_nGlyphs++;
598 CFX_Matrix matrix;
599 if (charpos.m_bGlyphAdjust)
600 matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1],
601 charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0);
602 matrix.Concat(1.0f, 0, 0, 1.0f, 0, 0);
603 const CFX_PathData* pPathData = pFaceCache->LoadGlyphPath(
604 pFont, charpos.m_GlyphIndex, charpos.m_FontCharWidth);
605 if (!pPathData)
606 return;
607
608 CFX_PathData TransformedPath(*pPathData);
609 if (charpos.m_bGlyphAdjust)
610 TransformedPath.Transform(&matrix);
611
612 CFX_ByteTextBuf buf;
613 buf << "/X" << ps_fontnum << " Ff/CharProcs get begin/" << ps_glyphindex
614 << "{n ";
615 for (int p = 0; p < TransformedPath.GetPointCount(); p++) {
616 FX_FLOAT x = TransformedPath.GetPointX(p), y = TransformedPath.GetPointY(p);
617 switch (TransformedPath.GetFlag(p) & FXPT_TYPE) {
618 case FXPT_MOVETO: {
619 buf << x << " " << y << " m\n";
620 break;
621 }
622 case FXPT_LINETO: {
623 buf << x << " " << y << " l\n";
624 break;
625 }
626 case FXPT_BEZIERTO: {
627 buf << x << " " << y << " " << TransformedPath.GetPointX(p + 1) << " "
628 << TransformedPath.GetPointY(p + 1) << " "
629 << TransformedPath.GetPointX(p + 2) << " "
630 << TransformedPath.GetPointY(p + 2) << " c\n";
631 p += 2;
632 break;
633 }
634 }
635 }
636 buf << "f}bind def end\n";
637 buf << "/X" << ps_fontnum << " Ff/Encoding get " << ps_glyphindex << "/"
638 << ps_glyphindex << " put\n";
639 m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize());
640 }
641
642 bool CFX_PSRenderer::DrawText(int nChars,
643 const FXTEXT_CHARPOS* pCharPos,
644 CFX_Font* pFont,
645 const CFX_Matrix* pObject2Device,
646 FX_FLOAT font_size,
647 uint32_t color) {
648 StartRendering();
649 int alpha = FXARGB_A(color);
650 if (alpha < 255)
651 return false;
652
653 if ((pObject2Device->a == 0 && pObject2Device->b == 0) ||
654 (pObject2Device->c == 0 && pObject2Device->d == 0)) {
655 return true;
656 }
657 SetColor(color);
658 CFX_ByteTextBuf buf;
659 buf << "q[" << pObject2Device->a << " " << pObject2Device->b << " "
660 << pObject2Device->c << " " << pObject2Device->d << " "
661 << pObject2Device->e << " " << pObject2Device->f << "]cm\n";
662
663 CFX_FontCache* pCache = CFX_GEModule::Get()->GetFontCache();
664 CFX_FaceCache* pFaceCache = pCache->GetCachedFace(pFont);
665 int last_fontnum = -1;
666 for (int i = 0; i < nChars; i++) {
667 int ps_fontnum, ps_glyphindex;
668 FindPSFontGlyph(pFaceCache, pFont, pCharPos[i], ps_fontnum, ps_glyphindex);
669 if (last_fontnum != ps_fontnum) {
670 buf << "/X" << ps_fontnum << " Ff " << font_size << " Fs Sf ";
671 last_fontnum = ps_fontnum;
672 }
673 buf << pCharPos[i].m_OriginX << " " << pCharPos[i].m_OriginY << " m";
674 CFX_ByteString hex;
675 hex.Format("<%02X>", ps_glyphindex);
676 buf << hex.AsStringC() << "Tj\n";
677 }
678 buf << "Q\n";
679 m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize());
680 pCache->ReleaseCachedFace(pFont);
681 return true;
682 }
683
684 void CFX_PSRenderer::WritePSBinary(const uint8_t* data, int len) {
685 uint8_t* dest_buf;
686 uint32_t dest_size;
687 CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule();
688 if (pEncoders &&
689 pEncoders->GetBasicModule()->A85Encode(data, len, dest_buf, dest_size)) {
690 m_pOutput->OutputPS((const FX_CHAR*)dest_buf, dest_size);
691 FX_Free(dest_buf);
692 } else {
693 m_pOutput->OutputPS((const FX_CHAR*)data, len);
694 }
695 }
OLDNEW
« no previous file with comments | « core/fxge/win32/fx_ge_ps.h ('k') | core/fxge/win32/fx_win32_device.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698