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

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

Issue 2393593002: Move core/fpdfapi/fpdf_render to core/fpdfapi/render (Closed)
Patch Set: Rebase to master Created 4 years, 2 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
(Empty)
1 // Copyright 2014 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/fpdfapi/fpdf_render/render_int.h"
8
9 #include <vector>
10
11 #include "core/fpdfapi/font/cpdf_cidfont.h"
12 #include "core/fpdfapi/font/cpdf_font.h"
13 #include "core/fpdfapi/font/cpdf_type3char.h"
14 #include "core/fpdfapi/font/cpdf_type3font.h"
15 #include "core/fpdfapi/fpdf_render/cpdf_renderoptions.h"
16 #include "core/fpdfapi/fpdf_render/cpdf_textrenderer.h"
17 #include "core/fpdfapi/fpdf_render/cpdf_type3cache.h"
18 #include "core/fpdfapi/page/cpdf_form.h"
19 #include "core/fpdfapi/page/cpdf_imageobject.h"
20 #include "core/fpdfapi/page/cpdf_pageobject.h"
21 #include "core/fpdfapi/page/cpdf_pathobject.h"
22 #include "core/fpdfapi/page/cpdf_textobject.h"
23 #include "core/fpdfapi/page/pageint.h"
24 #include "core/fpdfapi/parser/cpdf_dictionary.h"
25 #include "core/fpdfapi/parser/cpdf_document.h"
26 #include "core/fxge/cfx_facecache.h"
27 #include "core/fxge/cfx_fxgedevice.h"
28 #include "core/fxge/cfx_gemodule.h"
29 #include "core/fxge/cfx_graphstatedata.h"
30 #include "core/fxge/cfx_pathdata.h"
31 #include "core/fxge/cfx_renderdevice.h"
32
33 FX_BOOL CPDF_RenderStatus::ProcessText(CPDF_TextObject* textobj,
34 const CFX_Matrix* pObj2Device,
35 CFX_PathData* pClippingPath) {
36 if (textobj->m_nChars == 0)
37 return TRUE;
38
39 const TextRenderingMode text_render_mode = textobj->m_TextState.GetTextMode();
40 if (text_render_mode == TextRenderingMode::MODE_INVISIBLE)
41 return TRUE;
42
43 CPDF_Font* pFont = textobj->m_TextState.GetFont();
44 if (pFont->IsType3Font())
45 return ProcessType3Text(textobj, pObj2Device);
46
47 bool bFill = false;
48 bool bStroke = false;
49 bool bClip = false;
50 if (pClippingPath) {
51 bClip = true;
52 } else {
53 switch (text_render_mode) {
54 case TextRenderingMode::MODE_FILL:
55 case TextRenderingMode::MODE_FILL_CLIP:
56 bFill = true;
57 break;
58 case TextRenderingMode::MODE_STROKE:
59 case TextRenderingMode::MODE_STROKE_CLIP:
60 if (pFont->GetFace() ||
61 (pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_GLYPHPATH)) {
62 bStroke = true;
63 } else {
64 bFill = true;
65 }
66 break;
67 case TextRenderingMode::MODE_FILL_STROKE:
68 case TextRenderingMode::MODE_FILL_STROKE_CLIP:
69 bFill = true;
70 if (pFont->GetFace() ||
71 (pFont->GetSubstFont()->m_SubstFlags & FXFONT_SUBST_GLYPHPATH)) {
72 bStroke = true;
73 }
74 break;
75 case TextRenderingMode::MODE_INVISIBLE:
76 // Already handled above, but the compiler is not smart enough to
77 // realize it. Fall through.
78 ASSERT(false);
79 case TextRenderingMode::MODE_CLIP:
80 return TRUE;
81 }
82 }
83 FX_ARGB stroke_argb = 0;
84 FX_ARGB fill_argb = 0;
85 bool bPattern = false;
86 if (bStroke) {
87 if (textobj->m_ColorState.GetStrokeColor()->IsPattern()) {
88 bPattern = true;
89 } else {
90 stroke_argb = GetStrokeArgb(textobj);
91 }
92 }
93 if (bFill) {
94 if (textobj->m_ColorState.GetFillColor()->IsPattern()) {
95 bPattern = true;
96 } else {
97 fill_argb = GetFillArgb(textobj);
98 }
99 }
100 CFX_Matrix text_matrix;
101 textobj->GetTextMatrix(&text_matrix);
102 if (!IsAvailableMatrix(text_matrix))
103 return TRUE;
104
105 FX_FLOAT font_size = textobj->m_TextState.GetFontSize();
106 if (bPattern) {
107 DrawTextPathWithPattern(textobj, pObj2Device, pFont, font_size,
108 &text_matrix, bFill, bStroke);
109 return TRUE;
110 }
111 if (bClip || bStroke) {
112 const CFX_Matrix* pDeviceMatrix = pObj2Device;
113 CFX_Matrix device_matrix;
114 if (bStroke) {
115 const FX_FLOAT* pCTM = textobj->m_TextState.GetCTM();
116 if (pCTM[0] != 1.0f || pCTM[3] != 1.0f) {
117 CFX_Matrix ctm(pCTM[0], pCTM[1], pCTM[2], pCTM[3], 0, 0);
118 text_matrix.ConcatInverse(ctm);
119 device_matrix = ctm;
120 device_matrix.Concat(*pObj2Device);
121 pDeviceMatrix = &device_matrix;
122 }
123 }
124 int flag = 0;
125 if (bStroke && bFill) {
126 flag |= FX_FILL_STROKE;
127 flag |= FX_STROKE_TEXT_MODE;
128 }
129 if (textobj->m_GeneralState.GetStrokeAdjust())
130 flag |= FX_STROKE_ADJUST;
131 if (m_Options.m_Flags & RENDER_NOTEXTSMOOTH)
132 flag |= FXFILL_NOPATHSMOOTH;
133 return CPDF_TextRenderer::DrawTextPath(
134 m_pDevice, textobj->m_nChars, textobj->m_pCharCodes,
135 textobj->m_pCharPos, pFont, font_size, &text_matrix, pDeviceMatrix,
136 textobj->m_GraphState.GetObject(), fill_argb, stroke_argb,
137 pClippingPath, flag);
138 }
139 text_matrix.Concat(*pObj2Device);
140 return CPDF_TextRenderer::DrawNormalText(
141 m_pDevice, textobj->m_nChars, textobj->m_pCharCodes, textobj->m_pCharPos,
142 pFont, font_size, &text_matrix, fill_argb, &m_Options);
143 }
144
145 CPDF_Type3Cache* CPDF_RenderStatus::GetCachedType3(CPDF_Type3Font* pFont) {
146 if (!pFont->m_pDocument) {
147 return nullptr;
148 }
149 pFont->m_pDocument->GetPageData()->GetFont(pFont->GetFontDict(), FALSE);
150 return pFont->m_pDocument->GetRenderData()->GetCachedType3(pFont);
151 }
152 static void ReleaseCachedType3(CPDF_Type3Font* pFont) {
153 if (!pFont->m_pDocument) {
154 return;
155 }
156 pFont->m_pDocument->GetRenderData()->ReleaseCachedType3(pFont);
157 pFont->m_pDocument->GetPageData()->ReleaseFont(pFont->GetFontDict());
158 }
159
160 class CPDF_RefType3Cache {
161 public:
162 explicit CPDF_RefType3Cache(CPDF_Type3Font* pType3Font)
163 : m_dwCount(0), m_pType3Font(pType3Font) {}
164 ~CPDF_RefType3Cache() {
165 while (m_dwCount--) {
166 ReleaseCachedType3(m_pType3Font);
167 }
168 }
169 uint32_t m_dwCount;
170 CPDF_Type3Font* const m_pType3Font;
171 };
172
173 // TODO(npm): Font fallback for type 3 fonts? (Completely separate code!!)
174 FX_BOOL CPDF_RenderStatus::ProcessType3Text(CPDF_TextObject* textobj,
175 const CFX_Matrix* pObj2Device) {
176 CPDF_Type3Font* pType3Font = textobj->m_TextState.GetFont()->AsType3Font();
177 for (int i = 0; i < m_Type3FontCache.GetSize(); ++i) {
178 if (m_Type3FontCache.GetAt(i) == pType3Font)
179 return TRUE;
180 }
181
182 CFX_Matrix dCTM = m_pDevice->GetCTM();
183 FX_FLOAT sa = FXSYS_fabs(dCTM.a);
184 FX_FLOAT sd = FXSYS_fabs(dCTM.d);
185 CFX_Matrix text_matrix;
186 textobj->GetTextMatrix(&text_matrix);
187 CFX_Matrix char_matrix = pType3Font->GetFontMatrix();
188 FX_FLOAT font_size = textobj->m_TextState.GetFontSize();
189 char_matrix.Scale(font_size, font_size);
190 FX_ARGB fill_argb = GetFillArgb(textobj, TRUE);
191 int fill_alpha = FXARGB_A(fill_argb);
192 int device_class = m_pDevice->GetDeviceClass();
193 std::vector<FXTEXT_GLYPHPOS> glyphs;
194 if (device_class == FXDC_DISPLAY)
195 glyphs.resize(textobj->m_nChars);
196 else if (fill_alpha < 255)
197 return FALSE;
198
199 CPDF_RefType3Cache refTypeCache(pType3Font);
200 uint32_t* pChars = textobj->m_pCharCodes;
201 if (textobj->m_nChars == 1)
202 pChars = (uint32_t*)(&textobj->m_pCharCodes);
203
204 for (int iChar = 0; iChar < textobj->m_nChars; iChar++) {
205 uint32_t charcode = pChars[iChar];
206 if (charcode == (uint32_t)-1)
207 continue;
208
209 CPDF_Type3Char* pType3Char = pType3Font->LoadChar(charcode);
210 if (!pType3Char)
211 continue;
212
213 CFX_Matrix matrix = char_matrix;
214 matrix.e += iChar ? textobj->m_pCharPos[iChar - 1] : 0;
215 matrix.Concat(text_matrix);
216 matrix.Concat(*pObj2Device);
217 if (!pType3Char->LoadBitmap(m_pContext)) {
218 if (!glyphs.empty()) {
219 for (int i = 0; i < iChar; i++) {
220 const FXTEXT_GLYPHPOS& glyph = glyphs[i];
221 if (!glyph.m_pGlyph)
222 continue;
223
224 m_pDevice->SetBitMask(&glyph.m_pGlyph->m_Bitmap,
225 glyph.m_OriginX + glyph.m_pGlyph->m_Left,
226 glyph.m_OriginY - glyph.m_pGlyph->m_Top,
227 fill_argb);
228 }
229 glyphs.clear();
230 }
231 CPDF_GraphicStates* pStates = CloneObjStates(textobj, FALSE);
232 CPDF_RenderOptions Options = m_Options;
233 Options.m_Flags |= RENDER_FORCE_HALFTONE | RENDER_RECT_AA;
234 Options.m_Flags &= ~RENDER_FORCE_DOWNSAMPLE;
235 CPDF_Dictionary* pFormResource = nullptr;
236 if (pType3Char->m_pForm && pType3Char->m_pForm->m_pFormDict) {
237 pFormResource =
238 pType3Char->m_pForm->m_pFormDict->GetDictFor("Resources");
239 }
240 if (fill_alpha == 255) {
241 CPDF_RenderStatus status;
242 status.Initialize(m_pContext, m_pDevice, nullptr, nullptr, this,
243 pStates, &Options,
244 pType3Char->m_pForm->m_Transparency, m_bDropObjects,
245 pFormResource, FALSE, pType3Char, fill_argb);
246 status.m_Type3FontCache.Append(m_Type3FontCache);
247 status.m_Type3FontCache.Add(pType3Font);
248 m_pDevice->SaveState();
249 status.RenderObjectList(pType3Char->m_pForm.get(), &matrix);
250 m_pDevice->RestoreState(false);
251 } else {
252 CFX_FloatRect rect_f = pType3Char->m_pForm->CalcBoundingBox();
253 rect_f.Transform(&matrix);
254 FX_RECT rect = rect_f.GetOuterRect();
255 CFX_FxgeDevice bitmap_device;
256 if (!bitmap_device.Create((int)(rect.Width() * sa),
257 (int)(rect.Height() * sd), FXDIB_Argb,
258 nullptr)) {
259 return TRUE;
260 }
261 bitmap_device.GetBitmap()->Clear(0);
262 CPDF_RenderStatus status;
263 status.Initialize(m_pContext, &bitmap_device, nullptr, nullptr, this,
264 pStates, &Options,
265 pType3Char->m_pForm->m_Transparency, m_bDropObjects,
266 pFormResource, FALSE, pType3Char, fill_argb);
267 status.m_Type3FontCache.Append(m_Type3FontCache);
268 status.m_Type3FontCache.Add(pType3Font);
269 matrix.TranslateI(-rect.left, -rect.top);
270 matrix.Scale(sa, sd);
271 status.RenderObjectList(pType3Char->m_pForm.get(), &matrix);
272 m_pDevice->SetDIBits(bitmap_device.GetBitmap(), rect.left, rect.top);
273 }
274 delete pStates;
275 } else if (pType3Char->m_pBitmap) {
276 if (device_class == FXDC_DISPLAY) {
277 CPDF_Type3Cache* pCache = GetCachedType3(pType3Font);
278 refTypeCache.m_dwCount++;
279 CFX_GlyphBitmap* pBitmap = pCache->LoadGlyph(charcode, &matrix, sa, sd);
280 if (!pBitmap)
281 continue;
282
283 int origin_x = FXSYS_round(matrix.e);
284 int origin_y = FXSYS_round(matrix.f);
285 if (glyphs.empty()) {
286 m_pDevice->SetBitMask(&pBitmap->m_Bitmap, origin_x + pBitmap->m_Left,
287 origin_y - pBitmap->m_Top, fill_argb);
288 } else {
289 glyphs[iChar].m_pGlyph = pBitmap;
290 glyphs[iChar].m_OriginX = origin_x;
291 glyphs[iChar].m_OriginY = origin_y;
292 }
293 } else {
294 CFX_Matrix image_matrix = pType3Char->m_ImageMatrix;
295 image_matrix.Concat(matrix);
296 CPDF_ImageRenderer renderer;
297 if (renderer.Start(this, pType3Char->m_pBitmap.get(), fill_argb, 255,
298 &image_matrix, 0, FALSE)) {
299 renderer.Continue(nullptr);
300 }
301 if (!renderer.m_Result)
302 return FALSE;
303 }
304 }
305 }
306
307 if (glyphs.empty())
308 return TRUE;
309
310 FX_RECT rect = FXGE_GetGlyphsBBox(glyphs, 0, sa, sd);
311 CFX_DIBitmap bitmap;
312 if (!bitmap.Create(static_cast<int>(rect.Width() * sa),
313 static_cast<int>(rect.Height() * sd), FXDIB_8bppMask)) {
314 return TRUE;
315 }
316 bitmap.Clear(0);
317 for (const FXTEXT_GLYPHPOS& glyph : glyphs) {
318 if (!glyph.m_pGlyph)
319 continue;
320
321 bitmap.TransferBitmap(
322 static_cast<int>(
323 (glyph.m_OriginX + glyph.m_pGlyph->m_Left - rect.left) * sa),
324 static_cast<int>((glyph.m_OriginY - glyph.m_pGlyph->m_Top - rect.top) *
325 sd),
326 glyph.m_pGlyph->m_Bitmap.GetWidth(),
327 glyph.m_pGlyph->m_Bitmap.GetHeight(), &glyph.m_pGlyph->m_Bitmap, 0, 0);
328 }
329 m_pDevice->SetBitMask(&bitmap, rect.left, rect.top, fill_argb);
330 return TRUE;
331 }
332
333 class CPDF_CharPosList {
334 public:
335 CPDF_CharPosList();
336 ~CPDF_CharPosList();
337 void Load(int nChars,
338 uint32_t* pCharCodes,
339 FX_FLOAT* pCharPos,
340 CPDF_Font* pFont,
341 FX_FLOAT font_size);
342 FXTEXT_CHARPOS* m_pCharPos;
343 uint32_t m_nChars;
344 };
345
346 CPDF_CharPosList::CPDF_CharPosList() {
347 m_pCharPos = nullptr;
348 }
349
350 CPDF_CharPosList::~CPDF_CharPosList() {
351 FX_Free(m_pCharPos);
352 }
353
354 void CPDF_CharPosList::Load(int nChars,
355 uint32_t* pCharCodes,
356 FX_FLOAT* pCharPos,
357 CPDF_Font* pFont,
358 FX_FLOAT FontSize) {
359 m_pCharPos = FX_Alloc(FXTEXT_CHARPOS, nChars);
360 m_nChars = 0;
361 CPDF_CIDFont* pCIDFont = pFont->AsCIDFont();
362 FX_BOOL bVertWriting = pCIDFont && pCIDFont->IsVertWriting();
363 for (int iChar = 0; iChar < nChars; iChar++) {
364 uint32_t CharCode =
365 nChars == 1 ? (uint32_t)(uintptr_t)pCharCodes : pCharCodes[iChar];
366 if (CharCode == (uint32_t)-1) {
367 continue;
368 }
369 bool bVert = false;
370 FXTEXT_CHARPOS& charpos = m_pCharPos[m_nChars++];
371 if (pCIDFont) {
372 charpos.m_bFontStyle = true;
373 }
374 charpos.m_GlyphIndex = pFont->GlyphFromCharCode(CharCode, &bVert);
375 if (charpos.m_GlyphIndex != static_cast<uint32_t>(-1)) {
376 charpos.m_FallbackFontPosition = -1;
377 } else {
378 charpos.m_FallbackFontPosition =
379 pFont->FallbackFontFromCharcode(CharCode);
380 charpos.m_GlyphIndex = pFont->FallbackGlyphFromCharcode(
381 charpos.m_FallbackFontPosition, CharCode);
382 }
383 // TODO(npm): Figure out how this affects m_ExtGID
384 #if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
385 charpos.m_ExtGID = pFont->GlyphFromCharCodeExt(CharCode);
386 #endif
387 if (!pFont->IsEmbedded() && !pFont->IsCIDFont()) {
388 charpos.m_FontCharWidth = pFont->GetCharWidthF(CharCode);
389 } else {
390 charpos.m_FontCharWidth = 0;
391 }
392 charpos.m_OriginX = iChar ? pCharPos[iChar - 1] : 0;
393 charpos.m_OriginY = 0;
394 charpos.m_bGlyphAdjust = FALSE;
395 if (!pCIDFont) {
396 continue;
397 }
398 uint16_t CID = pCIDFont->CIDFromCharCode(CharCode);
399 if (bVertWriting) {
400 charpos.m_OriginY = charpos.m_OriginX;
401 charpos.m_OriginX = 0;
402 short vx, vy;
403 pCIDFont->GetVertOrigin(CID, vx, vy);
404 charpos.m_OriginX -= FontSize * vx / 1000;
405 charpos.m_OriginY -= FontSize * vy / 1000;
406 }
407 const uint8_t* pTransform = pCIDFont->GetCIDTransform(CID);
408 if (pTransform && !bVert) {
409 charpos.m_AdjustMatrix[0] = pCIDFont->CIDTransformToFloat(pTransform[0]);
410 charpos.m_AdjustMatrix[2] = pCIDFont->CIDTransformToFloat(pTransform[2]);
411 charpos.m_AdjustMatrix[1] = pCIDFont->CIDTransformToFloat(pTransform[1]);
412 charpos.m_AdjustMatrix[3] = pCIDFont->CIDTransformToFloat(pTransform[3]);
413 charpos.m_OriginX +=
414 pCIDFont->CIDTransformToFloat(pTransform[4]) * FontSize;
415 charpos.m_OriginY +=
416 pCIDFont->CIDTransformToFloat(pTransform[5]) * FontSize;
417 charpos.m_bGlyphAdjust = TRUE;
418 }
419 }
420 }
421
422 // static
423 FX_BOOL CPDF_TextRenderer::DrawTextPath(CFX_RenderDevice* pDevice,
424 int nChars,
425 uint32_t* pCharCodes,
426 FX_FLOAT* pCharPos,
427 CPDF_Font* pFont,
428 FX_FLOAT font_size,
429 const CFX_Matrix* pText2User,
430 const CFX_Matrix* pUser2Device,
431 const CFX_GraphStateData* pGraphState,
432 FX_ARGB fill_argb,
433 FX_ARGB stroke_argb,
434 CFX_PathData* pClippingPath,
435 int nFlag) {
436 CPDF_CharPosList CharPosList;
437 CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size);
438 if (CharPosList.m_nChars == 0)
439 return TRUE;
440 bool bDraw = true;
441 int32_t fontPosition = CharPosList.m_pCharPos[0].m_FallbackFontPosition;
442 uint32_t startIndex = 0;
443 for (uint32_t i = 0; i < CharPosList.m_nChars; i++) {
444 int32_t curFontPosition = CharPosList.m_pCharPos[i].m_FallbackFontPosition;
445 if (fontPosition == curFontPosition)
446 continue;
447 auto* font = fontPosition == -1
448 ? &pFont->m_Font
449 : pFont->m_FontFallbacks[fontPosition].get();
450 if (!pDevice->DrawTextPath(i - startIndex,
451 CharPosList.m_pCharPos + startIndex, font,
452 font_size, pText2User, pUser2Device, pGraphState,
453 fill_argb, stroke_argb, pClippingPath, nFlag)) {
454 bDraw = false;
455 }
456 fontPosition = curFontPosition;
457 startIndex = i;
458 }
459 auto* font = fontPosition == -1 ? &pFont->m_Font
460 : pFont->m_FontFallbacks[fontPosition].get();
461 if (!pDevice->DrawTextPath(CharPosList.m_nChars - startIndex,
462 CharPosList.m_pCharPos + startIndex, font,
463 font_size, pText2User, pUser2Device, pGraphState,
464 fill_argb, stroke_argb, pClippingPath, nFlag)) {
465 bDraw = false;
466 }
467 return bDraw;
468 }
469
470 // static
471 void CPDF_TextRenderer::DrawTextString(CFX_RenderDevice* pDevice,
472 FX_FLOAT origin_x,
473 FX_FLOAT origin_y,
474 CPDF_Font* pFont,
475 FX_FLOAT font_size,
476 const CFX_Matrix* pMatrix,
477 const CFX_ByteString& str,
478 FX_ARGB fill_argb,
479 FX_ARGB stroke_argb,
480 const CFX_GraphStateData* pGraphState,
481 const CPDF_RenderOptions* pOptions) {
482 if (pFont->IsType3Font())
483 return;
484
485 int nChars = pFont->CountChar(str.c_str(), str.GetLength());
486 if (nChars <= 0)
487 return;
488
489 int offset = 0;
490 uint32_t* pCharCodes;
491 FX_FLOAT* pCharPos;
492 std::vector<uint32_t> codes;
493 std::vector<FX_FLOAT> positions;
494 if (nChars == 1) {
495 pCharCodes = reinterpret_cast<uint32_t*>(
496 pFont->GetNextChar(str.c_str(), str.GetLength(), offset));
497 pCharPos = nullptr;
498 } else {
499 codes.resize(nChars);
500 positions.resize(nChars - 1);
501 FX_FLOAT cur_pos = 0;
502 for (int i = 0; i < nChars; i++) {
503 codes[i] = pFont->GetNextChar(str.c_str(), str.GetLength(), offset);
504 if (i)
505 positions[i - 1] = cur_pos;
506 cur_pos += pFont->GetCharWidthF(codes[i]) * font_size / 1000;
507 }
508 pCharCodes = codes.data();
509 pCharPos = positions.data();
510 }
511 CFX_Matrix matrix;
512 if (pMatrix)
513 matrix = *pMatrix;
514
515 matrix.e = origin_x;
516 matrix.f = origin_y;
517
518 if (stroke_argb == 0) {
519 DrawNormalText(pDevice, nChars, pCharCodes, pCharPos, pFont, font_size,
520 &matrix, fill_argb, pOptions);
521 } else {
522 DrawTextPath(pDevice, nChars, pCharCodes, pCharPos, pFont, font_size,
523 &matrix, nullptr, pGraphState, fill_argb, stroke_argb, nullptr,
524 0);
525 }
526 }
527
528 // static
529 FX_BOOL CPDF_TextRenderer::DrawNormalText(CFX_RenderDevice* pDevice,
530 int nChars,
531 uint32_t* pCharCodes,
532 FX_FLOAT* pCharPos,
533 CPDF_Font* pFont,
534 FX_FLOAT font_size,
535 const CFX_Matrix* pText2Device,
536 FX_ARGB fill_argb,
537 const CPDF_RenderOptions* pOptions) {
538 CPDF_CharPosList CharPosList;
539 CharPosList.Load(nChars, pCharCodes, pCharPos, pFont, font_size);
540 if (CharPosList.m_nChars == 0)
541 return TRUE;
542 int FXGE_flags = 0;
543 if (pOptions) {
544 uint32_t dwFlags = pOptions->m_Flags;
545 if (dwFlags & RENDER_CLEARTYPE) {
546 FXGE_flags |= FXTEXT_CLEARTYPE;
547 if (dwFlags & RENDER_BGR_STRIPE) {
548 FXGE_flags |= FXTEXT_BGR_STRIPE;
549 }
550 }
551 if (dwFlags & RENDER_NOTEXTSMOOTH) {
552 FXGE_flags |= FXTEXT_NOSMOOTH;
553 }
554 if (dwFlags & RENDER_PRINTGRAPHICTEXT) {
555 FXGE_flags |= FXTEXT_PRINTGRAPHICTEXT;
556 }
557 if (dwFlags & RENDER_NO_NATIVETEXT) {
558 FXGE_flags |= FXTEXT_NO_NATIVETEXT;
559 }
560 if (dwFlags & RENDER_PRINTIMAGETEXT) {
561 FXGE_flags |= FXTEXT_PRINTIMAGETEXT;
562 }
563 } else {
564 FXGE_flags = FXTEXT_CLEARTYPE;
565 }
566 if (pFont->IsCIDFont()) {
567 FXGE_flags |= FXFONT_CIDFONT;
568 }
569 bool bDraw = true;
570 int32_t fontPosition = CharPosList.m_pCharPos[0].m_FallbackFontPosition;
571 uint32_t startIndex = 0;
572 for (uint32_t i = 0; i < CharPosList.m_nChars; i++) {
573 int32_t curFontPosition = CharPosList.m_pCharPos[i].m_FallbackFontPosition;
574 if (fontPosition == curFontPosition)
575 continue;
576 auto* font = fontPosition == -1
577 ? &pFont->m_Font
578 : pFont->m_FontFallbacks[fontPosition].get();
579 if (!pDevice->DrawNormalText(
580 i - startIndex, CharPosList.m_pCharPos + startIndex, font,
581 font_size, pText2Device, fill_argb, FXGE_flags)) {
582 bDraw = false;
583 }
584 fontPosition = curFontPosition;
585 startIndex = i;
586 }
587 auto* font = fontPosition == -1 ? &pFont->m_Font
588 : pFont->m_FontFallbacks[fontPosition].get();
589 if (!pDevice->DrawNormalText(CharPosList.m_nChars - startIndex,
590 CharPosList.m_pCharPos + startIndex, font,
591 font_size, pText2Device, fill_argb,
592 FXGE_flags)) {
593 bDraw = false;
594 }
595 return bDraw;
596 }
597
598 void CPDF_RenderStatus::DrawTextPathWithPattern(const CPDF_TextObject* textobj,
599 const CFX_Matrix* pObj2Device,
600 CPDF_Font* pFont,
601 FX_FLOAT font_size,
602 const CFX_Matrix* pTextMatrix,
603 FX_BOOL bFill,
604 FX_BOOL bStroke) {
605 if (!bStroke) {
606 CPDF_PathObject path;
607 std::vector<std::unique_ptr<CPDF_TextObject>> pCopy;
608 pCopy.push_back(std::unique_ptr<CPDF_TextObject>(textobj->Clone()));
609 path.m_bStroke = FALSE;
610 path.m_FillType = FXFILL_WINDING;
611 path.m_ClipPath.AppendTexts(&pCopy);
612 path.m_ColorState = textobj->m_ColorState;
613 path.m_Path.AppendRect(textobj->m_Left, textobj->m_Bottom, textobj->m_Right,
614 textobj->m_Top);
615 path.m_Left = textobj->m_Left;
616 path.m_Bottom = textobj->m_Bottom;
617 path.m_Right = textobj->m_Right;
618 path.m_Top = textobj->m_Top;
619 RenderSingleObject(&path, pObj2Device);
620 return;
621 }
622 CPDF_CharPosList CharPosList;
623 CharPosList.Load(textobj->m_nChars, textobj->m_pCharCodes,
624 textobj->m_pCharPos, pFont, font_size);
625 for (uint32_t i = 0; i < CharPosList.m_nChars; i++) {
626 FXTEXT_CHARPOS& charpos = CharPosList.m_pCharPos[i];
627 auto font =
628 charpos.m_FallbackFontPosition == -1
629 ? &pFont->m_Font
630 : pFont->m_FontFallbacks[charpos.m_FallbackFontPosition].get();
631 const CFX_PathData* pPath =
632 font->LoadGlyphPath(charpos.m_GlyphIndex, charpos.m_FontCharWidth);
633 if (!pPath) {
634 continue;
635 }
636 CPDF_PathObject path;
637 path.m_GraphState = textobj->m_GraphState;
638 path.m_ColorState = textobj->m_ColorState;
639 CFX_Matrix matrix;
640 if (charpos.m_bGlyphAdjust)
641 matrix.Set(charpos.m_AdjustMatrix[0], charpos.m_AdjustMatrix[1],
642 charpos.m_AdjustMatrix[2], charpos.m_AdjustMatrix[3], 0, 0);
643 matrix.Concat(font_size, 0, 0, font_size, charpos.m_OriginX,
644 charpos.m_OriginY);
645 path.m_Path.Append(pPath, &matrix);
646 path.m_Matrix = *pTextMatrix;
647 path.m_bStroke = bStroke;
648 path.m_FillType = bFill ? FXFILL_WINDING : 0;
649 path.CalcBoundingBox();
650 ProcessPath(&path, pObj2Device);
651 }
652 }
OLDNEW
« no previous file with comments | « core/fpdfapi/fpdf_render/fpdf_render_pattern_embeddertest.cpp ('k') | core/fpdfapi/fpdf_render/render_int.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698