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