• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 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 #include "core/fxge/cfx_defaultrenderdevice.h"
6 #include "core/fxge/cfx_font.h"
7 #include "core/fxge/cfx_graphstatedata.h"
8 #include "core/fxge/cfx_pathdata.h"
9 #include "core/fxge/cfx_renderdevice.h"
10 #include "core/fxge/skia/fx_skia_device.h"
11 #include "core/fxge/text_char_pos.h"
12 #include "fpdfsdk/cpdfsdk_helpers.h"
13 #include "public/cpp/fpdf_scopers.h"
14 #include "public/fpdfview.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 #include "third_party/skia/include/core/SkPictureRecorder.h"
17 
18 namespace {
19 
20 struct State {
21   enum class Change { kNo, kYes };
22   enum class Save { kNo, kYes };
23   enum class Clip { kNo, kSame, kDifferentPath, kDifferentMatrix };
24   enum class Graphic { kNone, kPath, kText };
25 
26   Change m_change;
27   Save m_save;
28   Clip m_clip;
29   Graphic m_graphic;
30   uint32_t m_pixel;
31 };
32 
EmptyTest(CFX_SkiaDeviceDriver * driver,const State &)33 void EmptyTest(CFX_SkiaDeviceDriver* driver, const State&) {
34   driver->SaveState();
35   driver->RestoreState(true);
36   driver->RestoreState(false);
37 }
38 
CommonTest(CFX_SkiaDeviceDriver * driver,const State & state)39 void CommonTest(CFX_SkiaDeviceDriver* driver, const State& state) {
40   TextCharPos charPos[1];
41   charPos[0].m_Origin = CFX_PointF(0, 1);
42   charPos[0].m_GlyphIndex = 1;
43   charPos[0].m_FontCharWidth = 4u;
44 
45   CFX_Font font;
46   float fontSize = 1;
47   CFX_PathData clipPath, clipPath2;
48   clipPath.AppendRect(0, 0, 3, 1);
49   clipPath2.AppendRect(0, 0, 2, 1);
50   CFX_Matrix clipMatrix;
51   CFX_Matrix clipMatrix2(1, 0, 0, 1, 0, 1);
52   driver->SaveState();
53   CFX_PathData path1;
54   path1.AppendRect(0, 0, 1, 2);
55 
56   CFX_Matrix matrix;
57   CFX_Matrix matrix2;
58   matrix2.Translate(1, 0);
59   CFX_GraphStateData graphState;
60   if (state.m_save == State::Save::kYes)
61     driver->SaveState();
62   if (state.m_clip != State::Clip::kNo)
63     driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
64   if (state.m_graphic == State::Graphic::kPath) {
65     driver->DrawPath(&path1, &matrix, &graphState, 0xFF112233, 0,
66                      FXFILL_WINDING, BlendMode::kNormal);
67   } else if (state.m_graphic == State::Graphic::kText) {
68     driver->DrawDeviceText(SK_ARRAY_COUNT(charPos), charPos, &font, matrix,
69                            fontSize, 0xFF445566);
70   }
71   if (state.m_save == State::Save::kYes)
72     driver->RestoreState(true);
73   CFX_PathData path2;
74   path2.AppendRect(0, 0, 2, 2);
75   if (state.m_change == State::Change::kYes) {
76     if (state.m_graphic == State::Graphic::kPath)
77       graphState.m_LineCap = CFX_GraphStateData::LineCapRound;
78     else if (state.m_graphic == State::Graphic::kText)
79       fontSize = 2;
80   }
81   if (state.m_clip == State::Clip::kSame)
82     driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
83   else if (state.m_clip == State::Clip::kDifferentPath)
84     driver->SetClip_PathFill(&clipPath2, &clipMatrix, 0);
85   else if (state.m_clip == State::Clip::kDifferentMatrix)
86     driver->SetClip_PathFill(&clipPath, &clipMatrix2, 0);
87   if (state.m_graphic == State::Graphic::kPath) {
88     driver->DrawPath(&path2, &matrix2, &graphState, 0xFF112233, 0,
89                      FXFILL_WINDING, BlendMode::kNormal);
90   } else if (state.m_graphic == State::Graphic::kText) {
91     driver->DrawDeviceText(SK_ARRAY_COUNT(charPos), charPos, &font, matrix2,
92                            fontSize, 0xFF445566);
93   }
94   if (state.m_save == State::Save::kYes)
95     driver->RestoreState(false);
96   driver->RestoreState(false);
97 }
98 
OutOfSequenceClipTest(CFX_SkiaDeviceDriver * driver,const State &)99 void OutOfSequenceClipTest(CFX_SkiaDeviceDriver* driver, const State&) {
100   CFX_PathData clipPath;
101   clipPath.AppendRect(1, 0, 3, 1);
102   CFX_Matrix clipMatrix;
103   driver->SaveState();
104   driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
105   driver->RestoreState(true);
106   driver->SaveState();
107   driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
108   driver->RestoreState(false);
109   driver->RestoreState(false);
110 
111   driver->SaveState();
112   driver->SaveState();
113   driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
114   driver->RestoreState(true);
115   driver->SetClip_PathFill(&clipPath, &clipMatrix, 0);
116   driver->RestoreState(false);
117   driver->RestoreState(false);
118 }
119 
Harness(void (* Test)(CFX_SkiaDeviceDriver *,const State &),const State & state)120 void Harness(void (*Test)(CFX_SkiaDeviceDriver*, const State&),
121              const State& state) {
122   constexpr int kWidth = 4;
123   constexpr int kHeight = 1;
124   ScopedFPDFBitmap bitmap(FPDFBitmap_Create(kWidth, kHeight, 1));
125   ASSERT_TRUE(bitmap);
126   FPDFBitmap_FillRect(bitmap.get(), 0, 0, kWidth, kHeight, 0x00000000);
127   CFX_DefaultRenderDevice device;
128   RetainPtr<CFX_DIBitmap> pBitmap(CFXDIBitmapFromFPDFBitmap(bitmap.get()));
129   device.Attach(pBitmap, false, nullptr, false);
130   auto* driver = static_cast<CFX_SkiaDeviceDriver*>(device.GetDeviceDriver());
131   (*Test)(driver, state);
132   driver->Flush();
133   uint32_t pixel = pBitmap->GetPixel(0, 0);
134   EXPECT_EQ(state.m_pixel, pixel);
135 #ifdef SK_DEBUG
136   if (!driver)  // force dump to be linked in so it can be called from debugger
137     driver->Dump();
138 #endif
139 }
140 
141 }  // namespace
142 
TEST(fxge,SkiaStateEmpty)143 TEST(fxge, SkiaStateEmpty) {
144   Harness(&EmptyTest, {});
145 }
146 
TEST(fxge,SkiaStatePath)147 TEST(fxge, SkiaStatePath) {
148   Harness(&CommonTest, {State::Change::kNo, State::Save::kYes,
149                         State::Clip::kSame, State::Graphic::kPath, 0xFF112233});
150   Harness(&CommonTest,
151           {State::Change::kNo, State::Save::kYes, State::Clip::kDifferentPath,
152            State::Graphic::kPath, 0xFF112233});
153   Harness(&CommonTest, {State::Change::kNo, State::Save::kYes, State::Clip::kNo,
154                         State::Graphic::kPath, 0xFF112233});
155   Harness(&CommonTest, {State::Change::kYes, State::Save::kNo, State::Clip::kNo,
156                         State::Graphic::kPath, 0xFF112233});
157   Harness(&CommonTest, {State::Change::kNo, State::Save::kNo, State::Clip::kNo,
158                         State::Graphic::kPath, 0xFF112233});
159 }
160 
161 #ifdef _SKIA_SUPPORT_
162 // TODO(crbug.com/pdfium/11): Fix this test and enable.
TEST(fxge,DISABLED_SkiaStateText)163 TEST(fxge, DISABLED_SkiaStateText) {
164   Harness(&CommonTest,
165           {State::Change::kNo, State::Save::kYes, State::Clip::kDifferentMatrix,
166            State::Graphic::kText, 0xFF445566});
167   Harness(&CommonTest, {State::Change::kNo, State::Save::kYes,
168                         State::Clip::kSame, State::Graphic::kText, 0xFF445566});
169 }
170 #endif
171 
TEST(fxge,SkiaStateOOSClip)172 TEST(fxge, SkiaStateOOSClip) {
173   Harness(&OutOfSequenceClipTest, {});
174 }
175