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

Side by Side Diff: core/src/fpdfapi/fpdf_render/fpdf_render_text.cpp

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

Powered by Google App Engine
This is Rietveld 408576698