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