1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved. 2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Use of this source code is governed by a BSD-style license that can be 3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// found in the LICENSE file. 4e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 5e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov 7e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "../../../include/fxge/fx_ge.h" 8e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "../../../include/fpdfapi/fpdf_render.h" 9e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "../../../include/fpdfapi/fpdf_pageobj.h" 10e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "../fpdf_page/pageint.h" 11e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "render_int.h" 12e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovextern FX_BOOL IsAvailableMatrix(const CFX_AffineMatrix& matrix); 13e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_Type3Cache::~CPDF_Type3Cache() 14e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 15e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_POSITION pos = m_SizeMap.GetStartPosition(); 16e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_ByteString Key; 17e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Type3Glyphs* pSizeCache = NULL; 18e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while(pos) { 19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pSizeCache = (CPDF_Type3Glyphs*)m_SizeMap.GetNextValue(pos); 20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete pSizeCache; 21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_SizeMap.RemoveAll(); 23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 24e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_GlyphBitmap* CPDF_Type3Cache::LoadGlyph(FX_DWORD charcode, const CFX_AffineMatrix* pMatrix, FX_FLOAT retinaScaleX, FX_FLOAT retinaScaleY) 25e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 26e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov _CPDF_UniqueKeyGen keygen; 27e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov keygen.Generate(4, FXSYS_round(pMatrix->a * 10000), FXSYS_round(pMatrix->b * 10000), 28e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXSYS_round(pMatrix->c * 10000), FXSYS_round(pMatrix->d * 10000)); 29e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_ByteStringC FaceGlyphsKey(keygen.m_Key, keygen.m_KeyLen); 30e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Type3Glyphs* pSizeCache = NULL; 31e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if(!m_SizeMap.Lookup(FaceGlyphsKey, (void*&)pSizeCache)) { 32e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pSizeCache = new CPDF_Type3Glyphs; 33e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_SizeMap.SetAt(FaceGlyphsKey, pSizeCache); 34e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 35e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_GlyphBitmap* pGlyphBitmap; 36e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if(pSizeCache->m_GlyphMap.Lookup((FX_LPVOID)(FX_UINTPTR)charcode, (void*&)pGlyphBitmap)) { 37e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pGlyphBitmap; 38e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 39e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphBitmap = RenderGlyph(pSizeCache, charcode, pMatrix, retinaScaleX, retinaScaleY); 40e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pSizeCache->m_GlyphMap.SetAt((FX_LPVOID)(FX_UINTPTR)charcode, pGlyphBitmap); 41e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pGlyphBitmap; 42e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 43e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_Type3Glyphs::~CPDF_Type3Glyphs() 44e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 45e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_POSITION pos = m_GlyphMap.GetStartPosition(); 46e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPVOID Key; 47e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_GlyphBitmap* pGlyphBitmap; 48e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while(pos) { 49e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_GlyphMap.GetNextAssoc(pos, Key, (void*&)pGlyphBitmap); 50e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete pGlyphBitmap; 51e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 52e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 53e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic int _AdjustBlue(FX_FLOAT pos, int& count, int blues[]) 54e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 55e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT min_distance = 1000000.0f * 1.0f; 56e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int closest_pos = -1; 57e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int i = 0; i < count; i ++) { 58e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT distance = (FX_FLOAT)FXSYS_fabs(pos - (FX_FLOAT)blues[i]); 59e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (distance < 1.0f * 80.0f / 100.0f && distance < min_distance) { 60e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov min_distance = distance; 61e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov closest_pos = i; 62e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 63e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 64e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (closest_pos >= 0) { 65e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return blues[closest_pos]; 66e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 67e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int new_pos = FXSYS_round(pos); 68e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (count == TYPE3_MAX_BLUES) { 69e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return new_pos; 70e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 71e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov blues[count++] = new_pos; 72e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return new_pos; 73e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 74e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CPDF_Type3Glyphs::AdjustBlue(FX_FLOAT top, FX_FLOAT bottom, int& top_line, int& bottom_line) 75e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 76e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov top_line = _AdjustBlue(top, m_TopBlueCount, m_TopBlue); 77e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bottom_line = _AdjustBlue(bottom, m_BottomBlueCount, m_BottomBlue); 78e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 79e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic FX_BOOL _IsScanLine1bpp(FX_LPBYTE pBuf, int width) 80e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 81e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int size = width / 8; 82e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int i = 0; i < size; i ++) 83e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pBuf[i]) { 84e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 85e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 86e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (width % 8) 87e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pBuf[width / 8] & (0xff << (8 - width % 8))) { 88e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 89e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 90e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 91e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 92e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic FX_BOOL _IsScanLine8bpp(FX_LPBYTE pBuf, int width) 93e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 94e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int i = 0; i < width; i ++) 95e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pBuf[i] > 0x40) { 96e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 97e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 98e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 99e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 100e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic int _DetectFirstLastScan(const CFX_DIBitmap* pBitmap, FX_BOOL bFirst) 101e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 102e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int height = pBitmap->GetHeight(), pitch = pBitmap->GetPitch(), width = pBitmap->GetWidth(); 103e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int bpp = pBitmap->GetBPP(); 104e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bpp > 8) { 105e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov width *= bpp / 8; 106e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 107e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPBYTE pBuf = pBitmap->GetBuffer(); 108e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int line = bFirst ? 0 : height - 1; 109e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int line_step = bFirst ? 1 : -1; 110e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int line_end = bFirst ? height : -1; 111e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while (line != line_end) { 112e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bpp == 1) { 113e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (_IsScanLine1bpp(pBuf + line * pitch, width)) { 114e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return line; 115e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 116e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 117e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (_IsScanLine8bpp(pBuf + line * pitch, width)) { 118e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return line; 119e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 120e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 121e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov line += line_step; 122e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 123e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return -1; 124e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 125e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_GlyphBitmap* CPDF_Type3Cache::RenderGlyph(CPDF_Type3Glyphs* pSize, FX_DWORD charcode, const CFX_AffineMatrix* pMatrix, FX_FLOAT retinaScaleX, FX_FLOAT retinaScaleY) 126e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 127e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Type3Char* pChar = m_pFont->LoadChar(charcode); 128e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pChar == NULL || pChar->m_pBitmap == NULL) { 129e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 130e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 131e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_DIBitmap* pBitmap = pChar->m_pBitmap; 132e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix image_matrix, text_matrix; 133e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov image_matrix = pChar->m_ImageMatrix; 134e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov text_matrix.Set(pMatrix->a, pMatrix->b, pMatrix->c, pMatrix->d, 0, 0); 135e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov image_matrix.Concat(text_matrix); 136e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_DIBitmap* pResBitmap = NULL; 137e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int left, top; 138e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (FXSYS_fabs(image_matrix.b) < FXSYS_fabs(image_matrix.a) / 100 && FXSYS_fabs(image_matrix.c) < FXSYS_fabs(image_matrix.d) / 100) { 139e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int top_line, bottom_line; 140e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov top_line = _DetectFirstLastScan(pBitmap, TRUE); 141e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bottom_line = _DetectFirstLastScan(pBitmap, FALSE); 142e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (top_line == 0 && bottom_line == pBitmap->GetHeight() - 1) { 143e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT top_y = image_matrix.d + image_matrix.f; 144e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT bottom_y = image_matrix.f; 145e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bFlipped = top_y > bottom_y; 146e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bFlipped) { 147e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT temp = top_y; 148e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov top_y = bottom_y; 149e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bottom_y = temp; 150e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 151e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pSize->AdjustBlue(top_y, bottom_y, top_line, bottom_line); 152e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pResBitmap = pBitmap->StretchTo((int)(FXSYS_round(image_matrix.a) * retinaScaleX), (int)((bFlipped ? top_line - bottom_line : bottom_line - top_line) * retinaScaleY)); 153e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov top = top_line; 154e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (image_matrix.a < 0) { 155e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov image_matrix.Scale(retinaScaleX, retinaScaleY); 156e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov left = FXSYS_round(image_matrix.e + image_matrix.a); 157e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 158e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov left = FXSYS_round(image_matrix.e); 159e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 160e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 161e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 162e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 163e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pResBitmap == NULL) { 164e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov image_matrix.Scale(retinaScaleX, retinaScaleY); 165e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pResBitmap = pBitmap->TransformTo(&image_matrix, left, top); 166e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 167e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pResBitmap == NULL) { 168e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 169e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 170e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_GlyphBitmap* pGlyph = new CFX_GlyphBitmap; 171e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyph->m_Left = left; 172e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyph->m_Top = -top; 173e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyph->m_Bitmap.TakeOver(pResBitmap); 174e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete pResBitmap; 175e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pGlyph; 176e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 177e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid _CPDF_UniqueKeyGen::Generate(int count, ...) 178e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 179e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov va_list argList; 180e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov va_start(argList, count); 181e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int i = 0; i < count; i ++) { 182e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int p = va_arg(argList, int); 183e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ((FX_DWORD*)m_Key)[i] = p; 184e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 185e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov va_end(argList); 186e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_KeyLen = count * sizeof(FX_DWORD); 187e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 188e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL CPDF_RenderStatus::ProcessText(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device, CFX_PathData* pClippingPath) 189e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 190e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if(textobj->m_nChars == 0) { 191e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 192e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 193e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int text_render_mode = textobj->m_TextState.GetObject()->m_TextMode; 194e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (text_render_mode == 3) { 195e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 196e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 197e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Font* pFont = textobj->m_TextState.GetFont(); 198e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetFontType() == PDFFONT_TYPE3) { 199e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return ProcessType3Text(textobj, pObj2Device); 200e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 201e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bFill = FALSE, bStroke = FALSE, bClip = FALSE; 202e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pClippingPath) { 203e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bClip = TRUE; 204e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 205e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov switch (text_render_mode) { 206e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case 0: 207e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case 4: 208e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bFill = TRUE; 209e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 210e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case 1: 211e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case 5: 212e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetFace() == NULL && !(pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_GLYPHPATH)) { 213e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bFill = TRUE; 214e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 215e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bStroke = TRUE; 216e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 217e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 218e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case 2: 219e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case 6: 220e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetFace() == NULL && !(pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_GLYPHPATH)) { 221e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bFill = TRUE; 222e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 223e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bFill = bStroke = TRUE; 224e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 225e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov break; 226e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case 3: 227e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov case 7: 228e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 229e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov default: 230e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bFill = TRUE; 231e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 232e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 233e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_ARGB stroke_argb = 0, fill_argb = 0; 234e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bPattern = FALSE; 235e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bStroke) { 236e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (textobj->m_ColorState.GetStrokeColor()->IsPattern()) { 237e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bPattern = TRUE; 238e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 239e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov stroke_argb = GetStrokeArgb(textobj); 240e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 241e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 242e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bFill) { 243e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (textobj->m_ColorState.GetFillColor()->IsPattern()) { 244e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bPattern = TRUE; 245e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 246e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov fill_argb = GetFillArgb(textobj); 247e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 248e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 249e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix text_matrix; 250e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov textobj->GetTextMatrix(&text_matrix); 251e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if(IsAvailableMatrix(text_matrix) == FALSE) { 252e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 253e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 254e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT font_size = textobj->m_TextState.GetFontSize(); 255e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bPattern) { 256e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov DrawTextPathWithPattern(textobj, pObj2Device, pFont, font_size, &text_matrix, bFill, bStroke); 257e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 258e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 259e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bClip || bStroke) { 260e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_AffineMatrix* pDeviceMatrix = pObj2Device; 261e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix device_matrix; 262e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bStroke) { 263e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const FX_FLOAT* pCTM = textobj->m_TextState.GetObject()->m_CTM; 264e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pCTM[0] != 1.0f || pCTM[3] != 1.0f) { 265e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix ctm(pCTM[0], pCTM[1], pCTM[2], pCTM[3], 0, 0); 266e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov text_matrix.ConcatInverse(ctm); 267e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov device_matrix.Copy(ctm); 268e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov device_matrix.Concat(*pObj2Device); 269e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pDeviceMatrix = &device_matrix; 270e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 271e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 272e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int flag = 0; 273e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bStroke && bFill) { 274e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov flag |= FX_FILL_STROKE; 275e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov flag |= FX_STROKE_TEXT_MODE; 276e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 277e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CPDF_GeneralStateData* pGeneralData = ((CPDF_PageObject*)textobj)->m_GeneralState; 278e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pGeneralData && pGeneralData->m_StrokeAdjust) { 279e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov flag |= FX_STROKE_ADJUST; 280e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 281e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH) { 282e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov flag |= FXFILL_NOPATHSMOOTH; 283e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 284e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return CPDF_TextRenderer::DrawTextPath(m_pDevice, textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, pFont, font_size, 285e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov &text_matrix, pDeviceMatrix, textobj->m_GraphState, fill_argb, stroke_argb, pClippingPath, flag); 286e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 287e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov text_matrix.Concat(*pObj2Device); 288e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return CPDF_TextRenderer::DrawNormalText(m_pDevice, textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, pFont, font_size, 289e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov &text_matrix, fill_argb, &m_Options); 290e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 291e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_Type3Cache* CPDF_RenderStatus::GetCachedType3(CPDF_Type3Font* pFont) 292e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 293e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->m_pDocument == NULL) { 294e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 295e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 296e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pFont->m_pDocument->GetPageData()->GetFont(pFont->GetFontDict(), FALSE); 297e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pFont->m_pDocument->GetRenderData()->GetCachedType3(pFont); 298e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 299e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic void ReleaseCachedType3(CPDF_Type3Font* pFont) 300e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 301e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->m_pDocument == NULL) { 302e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; 303e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 304e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pFont->m_pDocument->GetRenderData()->ReleaseCachedType3(pFont); 305e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pFont->m_pDocument->GetPageData()->ReleaseFont(pFont->GetFontDict()); 306e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 307e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL CPDF_Type3Char::LoadBitmap(CPDF_RenderContext* pContext) 308e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 309e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_pBitmap != NULL || m_pForm == NULL) { 310e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 311e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 312e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_pForm->CountObjects() == 1 && !m_bColored) { 313e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_PageObject *pPageObj = m_pForm->GetObjectAt(m_pForm->GetFirstObjectPosition()); 314e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pPageObj->m_Type == PDFPAGE_IMAGE) { 315e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_ImageObject* pImage = (CPDF_ImageObject*)pPageObj; 316e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_ImageMatrix = pImage->m_Matrix; 317e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_DIBSource* pSource = pImage->m_pImage->LoadDIBSource(); 318e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pSource) { 319e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pBitmap = pSource->Clone(); 320e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete pSource; 321e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 322e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete m_pForm; 323e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pForm = NULL; 324e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 325e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 326e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pPageObj->m_Type == PDFPAGE_INLINES) { 327e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_InlineImages *pInlines = (CPDF_InlineImages *)pPageObj; 328e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pInlines->m_pStream) { 329e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_ImageMatrix = pInlines->m_Matrices[0]; 330e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_DIBSource dibsrc; 331e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!dibsrc.Load(pContext->m_pDocument, pInlines->m_pStream, NULL, NULL, NULL, NULL)) { 332e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 333e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 334e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pBitmap = dibsrc.Clone(); 335e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete m_pForm; 336e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pForm = NULL; 337e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 338e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 339e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 340e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 341e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 342e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 343e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovclass CPDF_RefType3Cache 344e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 345e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovpublic: 346e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_RefType3Cache(CPDF_Type3Font* pType3Font) 347e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov { 348e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_dwCount = 0; 349e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pType3Font = pType3Font; 350e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 351e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ~CPDF_RefType3Cache() 352e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov { 353e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov while(m_dwCount--) { 354e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ReleaseCachedType3(m_pType3Font); 355e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 356e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 357e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_DWORD m_dwCount; 358e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Type3Font* m_pType3Font; 359e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}; 360e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL CPDF_RenderStatus::ProcessType3Text(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device) 361e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 362e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Type3Font* pType3Font = textobj->m_TextState.GetFont()->GetType3Font(); 363e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int j = 0; j < m_Type3FontCache.GetSize(); j++) 364e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if ((CPDF_Type3Font*)m_Type3FontCache.GetAt(j) == pType3Font) { 365e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 366e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 367e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_Matrix dCTM = m_pDevice->GetCTM(); 368e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT sa = FXSYS_fabs(dCTM.a); 369e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT sd = FXSYS_fabs(dCTM.d); 370e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix text_matrix; 371e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov textobj->GetTextMatrix(&text_matrix); 372e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix char_matrix = pType3Font->GetFontMatrix(); 373e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT font_size = textobj->m_TextState.GetFontSize(); 374e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov char_matrix.Scale(font_size, font_size); 375e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_ARGB fill_argb = GetFillArgb(textobj, TRUE); 376e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int fill_alpha = FXARGB_A(fill_argb); 377e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int device_class = m_pDevice->GetDeviceClass(); 378e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXTEXT_GLYPHPOS* pGlyphAndPos = NULL; 379e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (device_class == FXDC_DISPLAY) { 380e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphAndPos = FX_Alloc(FXTEXT_GLYPHPOS, textobj->m_nChars); 381e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (fill_alpha < 255) { 382e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 383e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 384e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_RefType3Cache refTypeCache(pType3Font); 385e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_DWORD *pChars = textobj->m_pCharCodes; 386e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (textobj->m_nChars == 1) { 387e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pChars = (FX_DWORD*)(&textobj->m_pCharCodes); 388e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 389e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int iChar = 0; iChar < textobj->m_nChars; iChar ++) { 390e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_DWORD charcode = pChars[iChar]; 391e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (charcode == (FX_DWORD) - 1) { 392e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 393e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 394e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Type3Char* pType3Char = pType3Font->LoadChar(charcode); 395e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pType3Char == NULL) { 396e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 397e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 398e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix matrix = char_matrix; 399e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.e += iChar ? textobj->m_pCharPos[iChar - 1] : 0; 400e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.Concat(text_matrix); 401e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.Concat(*pObj2Device); 402e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!pType3Char->LoadBitmap(m_pContext)) { 403e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pGlyphAndPos) { 404e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int i = 0; i < iChar; i ++) { 405e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[i]; 406e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (glyph.m_pGlyph == NULL) { 407e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 408e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 409e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pDevice->SetBitMask(&glyph.m_pGlyph->m_Bitmap, 410e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph.m_OriginX + glyph.m_pGlyph->m_Left, 411e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph.m_OriginY - glyph.m_pGlyph->m_Top, fill_argb); 412e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 413e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pGlyphAndPos); 414e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphAndPos = NULL; 415e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 416e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_GraphicStates* pStates = CloneObjStates(textobj, FALSE); 417e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_RenderOptions Options = m_Options; 418e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov Options.m_Flags |= RENDER_FORCE_HALFTONE | RENDER_RECT_AA; 419e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov Options.m_Flags &= ~RENDER_FORCE_DOWNSAMPLE; 420e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Dictionary* pFormResource = NULL; 421e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pType3Char->m_pForm && pType3Char->m_pForm->m_pFormDict) { 422e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pFormResource = pType3Char->m_pForm->m_pFormDict->GetDict(FX_BSTRC("Resources")); 423e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 424e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (fill_alpha == 255) { 425e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_RenderStatus status; 426e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov status.Initialize(m_pContext, m_pDevice, NULL, NULL, this, pStates, &Options, 427e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb); 428e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov status.m_Type3FontCache.Append(m_Type3FontCache); 429e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov status.m_Type3FontCache.Add(pType3Font); 430e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pDevice->SaveState(); 431e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov status.RenderObjectList(pType3Char->m_pForm, &matrix); 432e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pDevice->RestoreState(); 433e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 434e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_FloatRect rect_f = pType3Char->m_pForm->CalcBoundingBox(); 435e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov rect_f.Transform(&matrix); 436e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_RECT rect = rect_f.GetOutterRect(); 437e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_FxgeDevice bitmap_device; 438e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!bitmap_device.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_Argb)) { 439e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 440e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 441e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bitmap_device.GetBitmap()->Clear(0); 442e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_RenderStatus status; 443e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov status.Initialize(m_pContext, &bitmap_device, NULL, NULL, this, pStates, &Options, 444e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pType3Char->m_pForm->m_Transparency, m_bDropObjects, pFormResource, FALSE, pType3Char, fill_argb); 445e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov status.m_Type3FontCache.Append(m_Type3FontCache); 446e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov status.m_Type3FontCache.Add(pType3Font); 447e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.TranslateI(-rect.left, -rect.top); 448e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.Scale(sa, sd); 449e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov status.RenderObjectList(pType3Char->m_pForm, &matrix); 450e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pDevice->SetDIBits(bitmap_device.GetBitmap(), rect.left, rect.top); 451e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 452e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov delete pStates; 453e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else if (pType3Char->m_pBitmap) { 454e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (device_class == FXDC_DISPLAY) { 455e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Type3Cache* pCache = GetCachedType3(pType3Font); 456e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov refTypeCache.m_dwCount++; 457e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_GlyphBitmap* pBitmap = pCache->LoadGlyph(charcode, &matrix, sa, sd); 458e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pBitmap == NULL) { 459e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 460e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 461e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int origin_x = FXSYS_round(matrix.e); 462e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int origin_y = FXSYS_round(matrix.f); 463e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pGlyphAndPos) { 464e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphAndPos[iChar].m_pGlyph = pBitmap; 465e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphAndPos[iChar].m_OriginX = origin_x; 466e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGlyphAndPos[iChar].m_OriginY = origin_y; 467e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 468e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pDevice->SetBitMask(&pBitmap->m_Bitmap, origin_x + pBitmap->m_Left, origin_y - pBitmap->m_Top, fill_argb); 469e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 470e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 471e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix image_matrix = pType3Char->m_ImageMatrix; 472e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov image_matrix.Concat(matrix); 473e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_ImageRenderer renderer; 474e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (renderer.Start(this, pType3Char->m_pBitmap, fill_argb, 255, &image_matrix, 0, FALSE)) { 475e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov renderer.Continue(NULL); 476e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 477e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!renderer.m_Result) { 478e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return FALSE; 479e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 480e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 481e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 482e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 483e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pGlyphAndPos) { 484e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_RECT rect = FXGE_GetGlyphsBBox(pGlyphAndPos, textobj->m_nChars, 0, sa, sd); 485e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_DIBitmap bitmap; 486e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!bitmap.Create((int)(rect.Width() * sa), (int)(rect.Height() * sd), FXDIB_8bppMask)) { 487e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pGlyphAndPos); 488e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 489e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 490e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bitmap.Clear(0); 491e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int iChar = 0; iChar < textobj->m_nChars; iChar ++) { 492e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXTEXT_GLYPHPOS& glyph = pGlyphAndPos[iChar]; 493e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (glyph.m_pGlyph == NULL) { 494e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 495e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 496e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov bitmap.TransferBitmap((int)((glyph.m_OriginX + glyph.m_pGlyph->m_Left - rect.left) * sa), 497e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov (int)((glyph.m_OriginY - glyph.m_pGlyph->m_Top - rect.top) * sd), 498e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov glyph.m_pGlyph->m_Bitmap.GetWidth(), glyph.m_pGlyph->m_Bitmap.GetHeight(), 499e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov &glyph.m_pGlyph->m_Bitmap, 0, 0); 500e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 501e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pDevice->SetBitMask(&bitmap, rect.left, rect.top, fill_argb); 502e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pGlyphAndPos); 503e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 504e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return TRUE; 505e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 506e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovclass CPDF_CharPosList 507e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 508e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovpublic: 509e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_CharPosList(); 510e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ~CPDF_CharPosList(); 511e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov void Load(int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, CPDF_Font* pFont, FX_FLOAT font_size); 512e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXTEXT_CHARPOS* m_pCharPos; 513e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_DWORD m_nChars; 514e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}; 515e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_FLOAT _CIDTransformToFloat(FX_BYTE ch); 516e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_CharPosList::CPDF_CharPosList() 517e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 518e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pCharPos = NULL; 519e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 520e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_CharPosList::~CPDF_CharPosList() 521e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 522e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_pCharPos) { 523e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(m_pCharPos); 524e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 525e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 526e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CPDF_CharPosList::Load(int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, CPDF_Font* pFont, 527e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT FontSize) 528e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 529e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_pCharPos = FX_Alloc(FXTEXT_CHARPOS, nChars); 530e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov m_nChars = 0; 531e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_CIDFont* pCIDFont = pFont->GetCIDFont(); 532e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bVertWriting = pCIDFont && pCIDFont->IsVertWriting(); 533e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int iChar = 0; iChar < nChars; iChar ++) { 534e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_DWORD CharCode = nChars == 1 ? (FX_DWORD)(FX_UINTPTR)pCharCodes : pCharCodes[iChar]; 535e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (CharCode == (FX_DWORD) - 1) { 536e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 537e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 538e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_BOOL bVert = FALSE; 539e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXTEXT_CHARPOS& charpos = m_pCharPos[m_nChars++]; 540e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pCIDFont) { 541e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_bFontStyle = pCIDFont->IsFontStyleFromCharCode(CharCode); 542e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 543e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_GlyphIndex = pFont->GlyphFromCharCode(CharCode, &bVert); 544e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_ 545e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_ExtGID = pFont->GlyphFromCharCodeExt(CharCode); 546e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#endif 547e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!pFont->IsEmbedded() && pFont->GetFontType() != PDFFONT_CIDFONT) { 548e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_FontCharWidth = pFont->GetCharWidthF(CharCode); 549e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 550e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_FontCharWidth = 0; 551e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 552e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_OriginX = iChar ? pCharPos[iChar - 1] : 0; 553e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_OriginY = 0; 554e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_bGlyphAdjust = FALSE; 555e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pCIDFont == NULL) { 556e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 557e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 558e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_WORD CID = pCIDFont->CIDFromCharCode(CharCode); 559e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (bVertWriting) { 560e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_OriginY = charpos.m_OriginX; 561e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_OriginX = 0; 562e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov short vx, vy; 563e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCIDFont->GetVertOrigin(CID, vx, vy); 564e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_OriginX -= FontSize * vx / 1000; 565e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_OriginY -= FontSize * vy / 1000; 566e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 567e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_LPCBYTE pTransform = pCIDFont->GetCIDTransform(CID); 568e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pTransform && !bVert) { 569e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_AdjustMatrix[0] = _CIDTransformToFloat(pTransform[0]); 570e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_AdjustMatrix[2] = _CIDTransformToFloat(pTransform[2]); 571e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_AdjustMatrix[1] = _CIDTransformToFloat(pTransform[1]); 572e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_AdjustMatrix[3] = _CIDTransformToFloat(pTransform[3]); 573e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_OriginX += _CIDTransformToFloat(pTransform[4]) * FontSize; 574e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_OriginY += _CIDTransformToFloat(pTransform[5]) * FontSize; 575e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_bGlyphAdjust = TRUE; 576e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 577e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 578e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 579e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL CPDF_TextRenderer::DrawTextPath(CFX_RenderDevice* pDevice, int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, 580e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Font* pFont, FX_FLOAT font_size, 581e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_AffineMatrix* pText2User, const CFX_AffineMatrix* pUser2Device, 582e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_GraphStateData* pGraphState, 583e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_ARGB fill_argb, FX_ARGB stroke_argb, CFX_PathData* pClippingPath, int nFlag) 584e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 585e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_FontCache* pCache = pFont->m_pDocument ? pFont->m_pDocument->GetRenderData()->GetFontCache() : NULL; 586e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_CharPosList CharPosList; 587e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size); 588e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pDevice->DrawTextPath(CharPosList.m_nChars, CharPosList.m_pCharPos, 589e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov &pFont->m_Font, pCache, font_size, pText2User, pUser2Device, 590e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pGraphState, fill_argb, stroke_argb, pClippingPath, nFlag); 591e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 592e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice, int left, int top, CPDF_Font* pFont, int height, 593e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_ByteString& str, FX_ARGB argb) 594e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 595e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_RECT font_bbox; 596e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pFont->GetFontBBox(font_bbox); 597e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT font_size = (FX_FLOAT)height * 1000.0f / (FX_FLOAT)(font_bbox.top - font_bbox.bottom); 598e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT origin_x = (FX_FLOAT)left; 599e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT origin_y = (FX_FLOAT)top + font_size * (FX_FLOAT)font_bbox.top / 1000.0f; 600e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix matrix(1.0f, 0, 0, -1.0f, 0, 0); 601e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov DrawTextString(pDevice, origin_x, origin_y, pFont, font_size, &matrix, str, argb); 602e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 603e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice, FX_FLOAT origin_x, FX_FLOAT origin_y, CPDF_Font* pFont, FX_FLOAT font_size, 604e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_AffineMatrix* pMatrix, const CFX_ByteString& str, FX_ARGB fill_argb, 605e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_ARGB stroke_argb, const CFX_GraphStateData* pGraphState, const CPDF_RenderOptions* pOptions) 606e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 607e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int nChars = pFont->CountChar(str, str.GetLength()); 608e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (nChars == 0) { 609e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; 610e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 611e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_DWORD charcode; 612e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int offset = 0; 613e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_DWORD* pCharCodes; 614e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT* pCharPos; 615e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (nChars == 1) { 616e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charcode = pFont->GetNextChar(str, str.GetLength(), offset); 617e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCharCodes = (FX_DWORD*)(FX_UINTPTR)charcode; 618e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCharPos = NULL; 619e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 620e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCharCodes = FX_Alloc(FX_DWORD, nChars); 621e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCharPos = FX_Alloc(FX_FLOAT, nChars - 1); 622e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FLOAT cur_pos = 0; 623e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (int i = 0; i < nChars; i ++) { 624e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCharCodes[i] = pFont->GetNextChar(str, str.GetLength(), offset); 625e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (i) { 626e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCharPos[i - 1] = cur_pos; 627e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 628e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov cur_pos += pFont->GetCharWidthF(pCharCodes[i]) * font_size / 1000; 629e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 630e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 631e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix matrix; 632e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pMatrix) { 633e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix = *pMatrix; 634e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 635e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.e = origin_x; 636e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.f = origin_y; 637e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetFontType() == PDFFONT_TYPE3) 638e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ; 639e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov else if (stroke_argb == 0) { 640e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov DrawNormalText(pDevice, nChars, pCharCodes, pCharPos, pFont, font_size, &matrix, fill_argb, pOptions); 641e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else 642e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov DrawTextPath(pDevice, nChars, pCharCodes, pCharPos, pFont, font_size, &matrix, NULL, pGraphState, 643e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov fill_argb, stroke_argb, NULL); 644e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (nChars > 1) { 645e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pCharCodes); 646e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_Free(pCharPos); 647e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 648e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 649e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice, int nChars, FX_DWORD* pCharCodes, FX_FLOAT* pCharPos, 650e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Font* pFont, FX_FLOAT font_size, 651e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_AffineMatrix* pText2Device, 652e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_ARGB fill_argb, const CPDF_RenderOptions* pOptions) 653e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 654e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_FontCache* pCache = pFont->m_pDocument ? pFont->m_pDocument->GetRenderData()->GetFontCache() : NULL; 655e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_CharPosList CharPosList; 656e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size); 657e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int FXGE_flags = 0; 658e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pOptions) { 659e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_DWORD dwFlags = pOptions->m_Flags; 660e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (dwFlags & RENDER_CLEARTYPE) { 661e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXGE_flags |= FXTEXT_CLEARTYPE; 662e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (dwFlags & RENDER_BGR_STRIPE) { 663e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXGE_flags |= FXTEXT_BGR_STRIPE; 664e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 665e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 666e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (dwFlags & RENDER_NOTEXTSMOOTH) { 667e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXGE_flags |= FXTEXT_NOSMOOTH; 668e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 669e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (dwFlags & RENDER_PRINTGRAPHICTEXT) { 670e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXGE_flags |= FXTEXT_PRINTGRAPHICTEXT; 671e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 672e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (dwFlags & RENDER_NO_NATIVETEXT) { 673e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXGE_flags |= FXTEXT_NO_NATIVETEXT; 674e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 675e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (dwFlags & RENDER_PRINTIMAGETEXT) { 676e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXGE_flags |= FXTEXT_PRINTIMAGETEXT; 677e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 678e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 679e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXGE_flags = FXTEXT_CLEARTYPE; 680e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 681e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->GetFontType() & PDFFONT_CIDFONT) { 682e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXGE_flags |= FXFONT_CIDFONT; 683e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 684e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return pDevice->DrawNormalText(CharPosList.m_nChars, CharPosList.m_pCharPos, &pFont->m_Font, pCache, font_size, pText2Device, fill_argb, FXGE_flags); 685e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 686e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CPDF_RenderStatus::DrawTextPathWithPattern(const CPDF_TextObject* textobj, const CFX_AffineMatrix* pObj2Device, 687e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_Font* pFont, FX_FLOAT font_size, 688e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_AffineMatrix* pTextMatrix, FX_BOOL bFill, FX_BOOL bStroke) 689e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 690e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (!bStroke) { 691e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_PathObject path; 692e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_TextObject* pCopy = new CPDF_TextObject; 693e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCopy->Copy(textobj); 694e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_bStroke = FALSE; 695e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_FillType = FXFILL_WINDING; 696e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_ClipPath.AppendTexts(&pCopy, 1); 697e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_ColorState = textobj->m_ColorState; 698e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_Path.New()->AppendRect(textobj->m_Left, textobj->m_Bottom, textobj->m_Right, textobj->m_Top); 699e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_Left = textobj->m_Left; 700e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_Bottom = textobj->m_Bottom; 701e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_Right = textobj->m_Right; 702e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_Top = textobj->m_Top; 703e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov RenderSingleObject(&path, pObj2Device); 704e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return; 705e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 706e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_FontCache* pCache; 707e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pFont->m_pDocument) { 708e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCache = pFont->m_pDocument->GetRenderData()->GetFontCache(); 709e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } else { 710e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov pCache = CFX_GEModule::Get()->GetFontCache(); 711e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 712e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_FaceCache* pFaceCache = pCache->GetCachedFace(&pFont->m_Font); 713e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FX_FONTCACHE_DEFINE(pCache, &pFont->m_Font); 714e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_CharPosList CharPosList; 715e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CharPosList.Load(textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos, pFont, font_size); 716e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov for (FX_DWORD i = 0; i < CharPosList.m_nChars; i ++) { 717e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov FXTEXT_CHARPOS& charpos = CharPosList.m_pCharPos[i]; 718e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov const CFX_PathData* pPath = pFaceCache->LoadGlyphPath(&pFont->m_Font, charpos.m_GlyphIndex, 719e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_FontCharWidth); 720e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (pPath == NULL) { 721e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov continue; 722e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 723e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CPDF_PathObject path; 724e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_GraphState = textobj->m_GraphState; 725e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_ColorState = textobj->m_ColorState; 726e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov CFX_AffineMatrix matrix; 727e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (charpos.m_bGlyphAdjust) 728e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1], 729e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0); 730e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov matrix.Concat(font_size, 0, 0, font_size, charpos.m_OriginX, charpos.m_OriginY); 731e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_Path.New()->Append(pPath, &matrix); 732e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_Matrix = *pTextMatrix; 733e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_bStroke = bStroke; 734e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.m_FillType = bFill ? FXFILL_WINDING : 0; 735e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov path.CalcBoundingBox(); 736e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov ProcessPath(&path, pObj2Device); 737e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 738e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 739e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_PathData* CPDF_Font::LoadGlyphPath(FX_DWORD charcode, int dest_width) 740e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{ 741e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov int glyph_index = GlyphFromCharCode(charcode); 742e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov if (m_Font.m_Face == NULL) { 743e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return NULL; 744e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov } 745e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov return m_Font.LoadGlyphPath(glyph_index, dest_width); 746e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov} 747