summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/fpdfapi/cpdf_pagerendercontext.h2
-rw-r--r--core/fpdfapi/render/cpdf_renderstatus.cpp2
-rw-r--r--core/fxge/cfx_renderdevice.h2
-rw-r--r--core/fxge/ge/cfx_renderdevice.cpp11
-rw-r--r--core/fxge/ifx_renderdevicedriver.cpp4
-rw-r--r--core/fxge/ifx_renderdevicedriver.h3
-rw-r--r--core/fxge/skia/fx_skia_device.cpp452
-rw-r--r--core/fxge/skia/fx_skia_device.h7
-rw-r--r--fpdfsdk/fpdfformfill.cpp5
-rw-r--r--fpdfsdk/fpdfview.cpp1
10 files changed, 298 insertions, 191 deletions
diff --git a/core/fpdfapi/cpdf_pagerendercontext.h b/core/fpdfapi/cpdf_pagerendercontext.h
index 9ddd075778..27244e7fc3 100644
--- a/core/fpdfapi/cpdf_pagerendercontext.h
+++ b/core/fpdfapi/cpdf_pagerendercontext.h
@@ -21,10 +21,10 @@ class CPDF_PageRenderContext {
CPDF_PageRenderContext();
~CPDF_PageRenderContext();
+ std::unique_ptr<CPDF_AnnotList> m_pAnnots;
std::unique_ptr<CFX_RenderDevice> m_pDevice;
std::unique_ptr<CPDF_RenderContext> m_pContext;
std::unique_ptr<CPDF_ProgressiveRenderer> m_pRenderer;
- std::unique_ptr<CPDF_AnnotList> m_pAnnots;
std::unique_ptr<CPDF_RenderOptions> m_pOptions;
};
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index 88dbb030ce..b23b98cdb1 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -898,6 +898,7 @@ std::unique_ptr<CFX_DIBitmap> DrawPatternBitmap(
context.AppendLayer(pPattern->form(), &mtPattern2Bitmap);
context.Render(&bitmap_device, &options, nullptr);
#if defined _SKIA_SUPPORT_PATHS_
+ bitmap_device.Flush();
pBitmap->UnPreMultiply();
#endif
return pBitmap;
@@ -1553,6 +1554,7 @@ bool CPDF_RenderStatus::ProcessTransparency(CPDF_PageObject* pPageObj,
pFormResource, true);
bitmap_render.ProcessObjectNoClip(pPageObj, &new_matrix);
#if defined _SKIA_SUPPORT_PATHS_
+ bitmap_device.Flush();
bitmap->UnPreMultiply();
#endif
m_bStopped = bitmap_render.m_bStopped;
diff --git a/core/fxge/cfx_renderdevice.h b/core/fxge/cfx_renderdevice.h
index d38b2981ba..800d0c7c52 100644
--- a/core/fxge/cfx_renderdevice.h
+++ b/core/fxge/cfx_renderdevice.h
@@ -227,6 +227,8 @@ class CFX_RenderDevice {
int top,
int bitmap_alpha,
int blend_type);
+#endif
+#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_
void Flush();
#endif
diff --git a/core/fxge/ge/cfx_renderdevice.cpp b/core/fxge/ge/cfx_renderdevice.cpp
index 64fa6ff452..9c67a7d1e7 100644
--- a/core/fxge/ge/cfx_renderdevice.cpp
+++ b/core/fxge/ge/cfx_renderdevice.cpp
@@ -354,9 +354,13 @@ CFX_RenderDevice::CFX_RenderDevice()
m_RenderCaps(0),
m_DeviceClass(0) {}
-CFX_RenderDevice::~CFX_RenderDevice() {}
+CFX_RenderDevice::~CFX_RenderDevice() {
+#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_
+ Flush();
+#endif
+}
-#ifdef _SKIA_SUPPORT_
+#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_
void CFX_RenderDevice::Flush() {
m_pDeviceDriver.reset();
}
@@ -615,6 +619,9 @@ bool CFX_RenderDevice::DrawFillStrokePath(const CFX_PathData* pPathData,
blend_type)) {
return false;
}
+#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_
+ bitmap_device.GetDeviceDriver()->Flush();
+#endif
FX_RECT src_rect(0, 0, FXSYS_round(rect.Width() * fScaleX),
FXSYS_round(rect.Height() * fScaleY));
return m_pDeviceDriver->SetDIBits(&bitmap, 0, &src_rect, rect.left, rect.top,
diff --git a/core/fxge/ifx_renderdevicedriver.cpp b/core/fxge/ifx_renderdevicedriver.cpp
index 07a4c27277..77af00f430 100644
--- a/core/fxge/ifx_renderdevicedriver.cpp
+++ b/core/fxge/ifx_renderdevicedriver.cpp
@@ -99,3 +99,7 @@ bool IFX_RenderDeviceDriver::SetBitsWithMask(const CFX_DIBSource* pBitmap,
int blend_type) {
return false;
}
+
+#if defined _SKIA_SUPPORT_ || _SKIA_SUPPORT_PATHS_
+void IFX_RenderDeviceDriver::Flush() {}
+#endif
diff --git a/core/fxge/ifx_renderdevicedriver.h b/core/fxge/ifx_renderdevicedriver.h
index 6a99276eba..6a5b63ba32 100644
--- a/core/fxge/ifx_renderdevicedriver.h
+++ b/core/fxge/ifx_renderdevicedriver.h
@@ -103,6 +103,9 @@ class IFX_RenderDeviceDriver {
int top,
int bitmap_alpha,
int blend_type);
+#if defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_
+ virtual void Flush();
+#endif
};
#endif // CORE_FXGE_IFX_RENDERDEVICEDRIVER_H_
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 84db838807..9c0ea07b3c 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -155,28 +155,37 @@ void RgbByteOrderTransferBitmap(CFX_DIBitmap* pBitmap,
#define SHOW_SKIA_PATH 0 // set to 1 to print the path contents
#define DRAW_SKIA_CLIP 0 // set to 1 to draw a green rectangle around the clip
-void DebugShowSkiaPath(const SkPath& path) {
#if SHOW_SKIA_PATH
- char buffer[4096];
- sk_bzero(buffer, sizeof(buffer));
- SkMemoryWStream stream(buffer, sizeof(buffer));
- path.dump(&stream, false, false);
- printf("%s", buffer);
-#endif // SHOW_SKIA_PATH
+void DebugShowSkiaPaint(const SkPaint& paint) {
+ if (SkPaint::kFill_Style == paint.getStyle()) {
+ printf("fill 0x%08x\n", paint.getColor());
+ } else {
+ printf("stroke 0x%08x width %g\n", paint.getColor(),
+ paint.getStrokeWidth());
+ }
}
void DebugShowCanvasMatrix(const SkCanvas* canvas) {
-#if SHOW_SKIA_PATH
SkMatrix matrix = canvas->getTotalMatrix();
SkScalar m[9];
matrix.get9(m);
printf("matrix (%g,%g,%g) (%g,%g,%g) (%g,%g,%g)\n", m[0], m[1], m[2], m[3],
m[4], m[5], m[6], m[7], m[8]);
-#endif // SHOW_SKIA_PATH
}
+#endif // SHOW_SKIA_PATH
+void DebugShowSkiaPath(const SkPath& path) {
#if SHOW_SKIA_PATH
+ char buffer[4096];
+ sk_bzero(buffer, sizeof(buffer));
+ SkMemoryWStream stream(buffer, sizeof(buffer));
+ path.dump(&stream, false, false);
+ printf("%s", buffer);
+#endif // SHOW_SKIA_PATH
+}
+
void DebugShowCanvasClip(const SkCanvas* canvas) {
+#if SHOW_SKIA_PATH
SkRect local;
SkIRect device;
canvas->getClipBounds(&local);
@@ -187,8 +196,10 @@ void DebugShowCanvasClip(const SkCanvas* canvas) {
device.fRight, device.fBottom);
const SkClipStack* clipStack = canvas->getClipStack();
clipStack->dump();
+#endif // SHOW_SKIA_PATH
}
+#if SHOW_SKIA_PATH
void DebugShowSkiaPaint(const SkPaint& paint) {
if (SkPaint::kFill_Style == paint.getStyle()) {
printf("fill 0x%08x\n", paint.getColor());
@@ -634,7 +645,6 @@ bool Upsample(const CFX_DIBSource* pSource,
} // namespace
-#ifdef _SKIA_SUPPORT_
// Encapsulate the state used for successive text and path draws so that
// they can be combined.
class SkiaState {
@@ -644,19 +654,35 @@ class SkiaState {
kPath,
};
+ enum class Accumulator {
+ kNone,
+ kPath,
+ kText,
+ kOther,
+ };
+
// mark all cached state as uninitialized
- SkiaState()
- : m_pFont(nullptr),
+ explicit SkiaState(CFX_SkiaDeviceDriver* pDriver)
+ : m_pDriver(pDriver),
+ m_pFont(nullptr),
m_fontSize(0),
m_fillColor(0),
m_strokeColor(0),
m_blendType(0),
m_commandIndex(0),
- m_drawText(false),
- m_drawPath(false),
+ m_drawIndex(INT_MAX),
+ m_clipIndex(0),
+ m_type(Accumulator::kNone),
+ m_fillFullCover(false),
m_fillPath(false),
m_groupKnockout(false),
- m_debugDisable(false) {}
+ m_debugDisable(false)
+#if SHOW_SKIA_PATH
+ ,
+ m_debugSaveCounter(0)
+#endif
+ {
+ }
bool DrawPath(const CFX_PathData* pPathData,
const CFX_Matrix* pMatrix,
@@ -664,21 +690,20 @@ class SkiaState {
uint32_t fill_color,
uint32_t stroke_color,
int fill_mode,
- int blend_type,
- CFX_SkiaDeviceDriver* pDriver) {
+ int blend_type) {
if (m_debugDisable)
return false;
- if (m_commandIndex < m_commands.count())
- FlushCommands(pDriver);
- if (m_drawText)
- FlushText(pDriver);
- if (m_drawPath &&
- DrawChanged(pMatrix, pDrawState, fill_color, stroke_color, fill_mode,
- blend_type, pDriver->m_bGroupKnockout)) {
- FlushPath(pDriver);
- }
- if (!m_drawPath) {
+ Dump(__func__);
+ int drawIndex = SkTMin(m_drawIndex, m_commands.count());
+ if (Accumulator::kText == m_type || drawIndex != m_commandIndex ||
+ (Accumulator::kPath == m_type &&
+ DrawChanged(pMatrix, pDrawState, fill_color, stroke_color, fill_mode,
+ blend_type, m_pDriver->m_bGroupKnockout))) {
+ Flush();
+ }
+ if (Accumulator::kPath != m_type) {
m_skPath.reset();
+ m_fillFullCover = !!(fill_mode & FXFILL_FULLCOVER);
m_fillPath = (fill_mode & 3) && fill_color;
m_skPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE
? SkPath::kEvenOdd_FillType
@@ -688,27 +713,31 @@ class SkiaState {
m_fillColor = fill_color;
m_strokeColor = stroke_color;
m_blendType = blend_type;
- m_groupKnockout = pDriver->m_bGroupKnockout;
+ m_groupKnockout = m_pDriver->m_bGroupKnockout;
if (pMatrix)
m_drawMatrix = *pMatrix;
+ m_drawIndex = m_commandIndex;
+ m_type = Accumulator::kPath;
}
SkPath skPath = BuildPath(pPathData);
SkPoint delta;
if (MatrixOffset(pMatrix, &delta))
skPath.offset(delta.fX, delta.fY);
m_skPath.addPath(skPath);
- m_drawPath = true;
return true;
}
- void FlushPath(CFX_SkiaDeviceDriver* pDriver) {
+ void FlushPath() {
+ Dump(__func__);
SkMatrix skMatrix = ToSkMatrix(m_drawMatrix);
SkPaint skPaint;
skPaint.setAntiAlias(true);
+ if (m_fillFullCover)
+ skPaint.setBlendMode(SkBlendMode::kPlus);
int stroke_alpha = FXARGB_A(m_strokeColor);
if (stroke_alpha)
- pDriver->PaintStroke(&skPaint, &m_drawState, skMatrix);
- SkCanvas* skCanvas = pDriver->SkiaCanvas();
+ m_pDriver->PaintStroke(&skPaint, &m_drawState, skMatrix);
+ SkCanvas* skCanvas = m_pDriver->SkiaCanvas();
skCanvas->save();
skCanvas->concat(skMatrix);
if (m_fillPath) {
@@ -725,17 +754,24 @@ class SkiaState {
}
skPaint.setStyle(SkPaint::kFill_Style);
skPaint.setColor(m_fillColor);
+#ifdef _SKIA_SUPPORT_PATHS_
+ m_pDriver->PreMultiply();
+#endif // _SKIA_SUPPORT_PATHS_
+ DebugShowSkiaDrawPath(skCanvas, skPaint, *fillPath);
skCanvas->drawPath(*fillPath, skPaint);
}
if (stroke_alpha) {
- DebugShowSkiaPath(m_skPath);
- DebugShowCanvasMatrix(skCanvas);
skPaint.setStyle(SkPaint::kStroke_Style);
skPaint.setColor(m_strokeColor);
+#ifdef _SKIA_SUPPORT_PATHS_
+ m_pDriver->PreMultiply();
+#endif // _SKIA_SUPPORT_PATHS_
+ DebugShowSkiaDrawPath(skCanvas, skPaint, m_skPath);
skCanvas->drawPath(m_skPath, skPaint);
}
skCanvas->restore();
- m_drawPath = false;
+ m_drawIndex = INT_MAX;
+ m_type = Accumulator::kNone;
}
bool DrawText(int nChars,
@@ -743,31 +779,36 @@ class SkiaState {
CFX_Font* pFont,
const CFX_Matrix* pMatrix,
FX_FLOAT font_size,
- uint32_t color,
- CFX_SkiaDeviceDriver* pDriver) {
+ uint32_t color) {
if (m_debugDisable)
return false;
- if (m_commandIndex < m_commands.count())
- FlushCommands(pDriver);
- if (m_drawPath)
- FlushPath(pDriver);
- if (m_drawText && FontChanged(pFont, pMatrix, font_size, color))
- FlushText(pDriver);
- if (!m_drawText) {
+ Dump(__func__);
+ int drawIndex = SkTMin(m_drawIndex, m_commands.count());
+ if (Accumulator::kPath == m_type || drawIndex != m_commandIndex ||
+ (Accumulator::kText == m_type &&
+ FontChanged(pFont, pMatrix, font_size, color))) {
+ Flush();
+ }
+ if (Accumulator::kText != m_type) {
m_positions.setCount(0);
m_glyphs.setCount(0);
m_pFont = pFont;
m_fontSize = font_size;
m_fillColor = color;
m_drawMatrix = *pMatrix;
+ m_drawIndex = m_commandIndex;
+ m_type = Accumulator::kText;
}
int count = m_positions.count();
m_positions.setCount(nChars + count);
m_glyphs.setCount(nChars + count);
SkScalar flip = m_fontSize < 0 ? -1 : 1;
+ SkScalar vFlip = flip;
+ if (pFont->IsVertical())
+ vFlip *= -1;
for (int index = 0; index < nChars; ++index) {
const FXTEXT_CHARPOS& cp = pCharPos[index];
- m_positions[index + count] = {cp.m_OriginX * flip, cp.m_OriginY * flip};
+ m_positions[index + count] = {cp.m_OriginX * flip, cp.m_OriginY * vFlip};
m_glyphs[index + count] = (uint16_t)cp.m_GlyphIndex;
}
SkPoint delta;
@@ -775,13 +816,11 @@ class SkiaState {
for (int index = 0; index < nChars; ++index)
m_positions[index + count].offset(delta.fX * flip, -delta.fY * flip);
}
- m_drawText = true;
return true;
}
- void FlushText(CFX_SkiaDeviceDriver* pDriver) {
- SkScalar flip = m_fontSize < 0 ? -1 : 1;
- SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix, flip);
+ void FlushText() {
+ Dump(__func__);
SkPaint skPaint;
skPaint.setAntiAlias(true);
skPaint.setColor(m_fillColor);
@@ -793,60 +832,78 @@ class SkiaState {
skPaint.setHinting(SkPaint::kNo_Hinting);
skPaint.setTextSize(SkTAbs(m_fontSize));
skPaint.setSubpixelText(true);
- SkCanvas* skCanvas = pDriver->SkiaCanvas();
+ SkCanvas* skCanvas = m_pDriver->SkiaCanvas();
skCanvas->save();
+ SkScalar flip = m_fontSize < 0 ? -1 : 1;
+ SkMatrix skMatrix = ToFlippedSkMatrix(m_drawMatrix, flip);
skCanvas->concat(skMatrix);
+#ifdef _SKIA_SUPPORT_PATHS_
+ m_pDriver->PreMultiply();
+#endif // _SKIA_SUPPORT_PATHS_
skCanvas->drawPosText(m_glyphs.begin(), m_glyphs.count() * 2,
m_positions.begin(), skPaint);
skCanvas->restore();
- m_drawText = false;
+ m_drawIndex = INT_MAX;
+ m_type = Accumulator::kNone;
}
bool SetClipFill(const CFX_PathData* pPathData,
const CFX_Matrix* pMatrix,
- int fill_mode,
- CFX_SkiaDeviceDriver* pDriver) {
+ int fill_mode) {
if (m_debugDisable)
return false;
+ Dump(__func__);
SkPath skClipPath = BuildPath(pPathData);
skClipPath.setFillType((fill_mode & 3) == FXFILL_ALTERNATE
? SkPath::kEvenOdd_FillType
: SkPath::kWinding_FillType);
SkMatrix skMatrix = ToSkMatrix(*pMatrix);
skClipPath.transform(skMatrix);
- return SetClip(skClipPath, pDriver);
+ return SetClip(skClipPath);
}
- bool SetClip(const SkPath& skClipPath, CFX_SkiaDeviceDriver* pDriver) {
+ bool SetClip(const SkPath& skClipPath) {
+ // if a pending draw depends on clip state that is cached, flush it and draw
if (m_commandIndex < m_commands.count()) {
if (m_commands[m_commandIndex] == Clip::kPath &&
m_clips[m_commandIndex] == skClipPath) {
++m_commandIndex;
return true;
}
- FlushCommands(pDriver);
+ Flush();
+ }
+ while (m_clipIndex > m_commandIndex) {
+ do {
+ --m_clipIndex;
+ SkASSERT(m_clipIndex >= 0);
+ } while (m_commands[m_clipIndex] != Clip::kSave);
+ m_pDriver->SkiaCanvas()->restore();
+ }
+ if (m_commandIndex < m_commands.count()) {
+ m_commands[m_commandIndex] = Clip::kPath;
+ m_clips[m_commandIndex] = skClipPath;
+ } else {
+ m_commands.push(Clip::kPath);
+ m_clips.push_back(skClipPath);
}
- Flush(pDriver);
- m_commands.push(Clip::kPath);
++m_commandIndex;
- m_clips.push_back(skClipPath);
- return false;
+ return true;
}
bool SetClipStroke(const CFX_PathData* pPathData,
const CFX_Matrix* pMatrix,
- const CFX_GraphStateData* pGraphState,
- CFX_SkiaDeviceDriver* pDriver) {
+ const CFX_GraphStateData* pGraphState) {
if (m_debugDisable)
return false;
+ Dump(__func__);
SkPath skPath = BuildPath(pPathData);
SkMatrix skMatrix = ToSkMatrix(*pMatrix);
SkPaint skPaint;
- pDriver->PaintStroke(&skPaint, pGraphState, skMatrix);
+ m_pDriver->PaintStroke(&skPaint, pGraphState, skMatrix);
SkPath dst_path;
skPaint.getFillPath(skPath, &dst_path);
dst_path.transform(skMatrix);
- return SetClip(dst_path, pDriver);
+ return SetClip(dst_path);
}
bool MatrixOffset(const CFX_Matrix* pMatrix, SkPoint* delta) {
@@ -871,60 +928,38 @@ class SkiaState {
return true;
}
- void FlushCommands(CFX_SkiaDeviceDriver* pDriver) {
- if (m_commandIndex == m_commands.count())
- return;
- if (m_commandIndex < m_commands.count())
- pDriver->SkiaCanvas()->restore();
- int index = m_commands.count() - 1;
- if (m_commandIndex == index && m_commands[index] == Clip::kSave)
- return;
- for (; index > m_commandIndex; --index) {
- if (m_commands[index] == Clip::kSave)
- pDriver->SkiaCanvas()->restore();
- }
-
- if (m_commandIndex > 0)
- pDriver->SkiaCanvas()->save();
- while (index > 0 && m_commands[index] != Clip::kSave)
- --index;
- while (++index < m_commandIndex) {
- SkASSERT(m_commands[index] == Clip::kPath);
- pDriver->SkiaCanvas()->clipPath(m_clips[index], SkCanvas::kIntersect_Op,
- true);
- }
- m_commands.setCount(m_commandIndex);
- m_clips.resize_back(m_commandIndex);
- }
-
// returns true if caller should apply command to skia canvas
- bool ClipSave(CFX_SkiaDeviceDriver* pDriver) {
+ bool ClipSave() {
if (m_debugDisable)
return false;
+ Dump(__func__);
int count = m_commands.count();
- if (m_commandIndex < count) {
- if (m_commands[m_commandIndex] == Clip::kSave) {
+ if (m_commandIndex < count - 1) {
+ if (Clip::kSave == m_commands[m_commandIndex + 1]) {
++m_commandIndex;
return true;
}
- FlushCommands(pDriver);
+ Flush();
+ AdjustClip(m_commandIndex);
+ m_commands[++m_commandIndex] = Clip::kSave;
+ m_clips[m_commandIndex] = m_skEmptyPath;
+ } else {
+ AdjustClip(m_commandIndex);
+ m_commands.push(Clip::kSave);
+ m_clips.push_back(m_skEmptyPath);
+ ++m_commandIndex;
}
- Flush(pDriver);
- m_commands.push(Clip::kSave);
- ++m_commandIndex;
- m_clips.push_back(m_skEmptyPath);
- return false;
+ return true;
}
- bool ClipRestore(CFX_SkiaDeviceDriver* pDriver) {
+ bool ClipRestore() {
if (m_debugDisable)
return false;
- while (m_commandIndex > 0) {
- if (m_commands[--m_commandIndex] == Clip::kSave)
- return true;
+ Dump(__func__);
+ while (Clip::kSave != m_commands[--m_commandIndex]) {
+ SkASSERT(m_commandIndex > 0);
}
- Flush(pDriver);
- return false;
+ return true;
}
bool DrawChanged(const CFX_Matrix* pMatrix,
@@ -933,7 +968,7 @@ class SkiaState {
uint32_t stroke_color,
int fill_mode,
int blend_type,
- bool group_knockout) {
+ bool group_knockout) const {
return MatrixChanged(pMatrix, m_drawMatrix) ||
StateChanged(pState, m_drawState) || fill_color != m_fillColor ||
stroke_color != m_strokeColor ||
@@ -945,12 +980,13 @@ class SkiaState {
bool FontChanged(CFX_Font* pFont,
const CFX_Matrix* pMatrix,
FX_FLOAT font_size,
- uint32_t color) {
+ uint32_t color) const {
return pFont != m_pFont || MatrixChanged(pMatrix, m_drawMatrix) ||
font_size != m_fontSize || color != m_fillColor;
}
- bool MatrixChanged(const CFX_Matrix* pMatrix, const CFX_Matrix& refMatrix) {
+ bool MatrixChanged(const CFX_Matrix* pMatrix,
+ const CFX_Matrix& refMatrix) const {
CFX_Matrix identityMatrix;
if (!pMatrix)
pMatrix = &identityMatrix;
@@ -959,7 +995,7 @@ class SkiaState {
}
bool StateChanged(const CFX_GraphStateData* pState,
- const CFX_GraphStateData& refState) {
+ const CFX_GraphStateData& refState) const {
CFX_GraphStateData identityState;
if (!pState)
pState = &identityState;
@@ -971,7 +1007,7 @@ class SkiaState {
}
bool DashChanged(const CFX_GraphStateData* pState,
- const CFX_GraphStateData& refState) {
+ const CFX_GraphStateData& refState) const {
bool dashArray = pState && pState->m_DashArray;
if (!dashArray && !refState.m_DashArray)
return false;
@@ -983,39 +1019,97 @@ class SkiaState {
}
for (int index = 0; index < pState->m_DashCount; ++index) {
if (pState->m_DashArray[index] != refState.m_DashArray[index])
- return false;
+ return true;
}
return true;
}
- void Flush(CFX_SkiaDeviceDriver* pDriver) {
- if (m_drawPath)
- FlushPath(pDriver);
- if (m_drawText)
- FlushText(pDriver);
+ void AdjustClip(int limit) {
+ while (m_clipIndex > limit) {
+ do {
+ --m_clipIndex;
+ SkASSERT(m_clipIndex >= 0);
+ } while (m_commands[m_clipIndex] != Clip::kSave);
+ m_pDriver->SkiaCanvas()->restore();
+ }
+ while (m_clipIndex < limit) {
+ if (Clip::kSave == m_commands[m_clipIndex]) {
+ m_pDriver->SkiaCanvas()->save();
+ } else {
+ SkASSERT(Clip::kPath == m_commands[m_clipIndex]);
+ m_pDriver->SkiaCanvas()->clipPath(m_clips[m_clipIndex],
+ SkCanvas::kIntersect_Op, true);
+ }
+ ++m_clipIndex;
+ }
+ }
+
+ void Flush() {
+ if (m_debugDisable)
+ return;
+ Dump(__func__);
+ if (Accumulator::kPath == m_type || Accumulator::kText == m_type) {
+ AdjustClip(SkTMin(m_drawIndex, m_commands.count()));
+ Accumulator::kPath == m_type ? FlushPath() : FlushText();
+ }
}
- void Dump(const CFX_SkiaDeviceDriver* pDriver) const {
+ void FlushForDraw() {
+ if (m_debugDisable)
+ return;
+ Flush(); // draw any pending text or path
+ AdjustClip(m_commandIndex); // set up clip stack with any pending state
+ }
+
+#if SHOW_SKIA_PATH
+ void DumpPrefix(int index) const {
+ if (index != m_commandIndex && index != m_drawIndex &&
+ index != m_clipIndex) {
+ printf(" ");
+ return;
+ }
+ printf("%c%c%c> ", index == m_commandIndex ? 'x' : '-',
+ index == m_drawIndex ? 'd' : '-', index == m_clipIndex ? 'c' : '-');
+ }
+
+ void DumpEndPrefix() const {
+ int index = m_commands.count();
+ if (index != m_commandIndex && index > m_drawIndex && index != m_clipIndex)
+ return;
+ printf("%c%c%c>\n", index == m_commandIndex ? 'x' : '-',
+ index <= m_drawIndex ? 'd' : '-', index == m_clipIndex ? 'c' : '-');
+ }
+#endif // SHOW_SKIA_PATH
+
+ void Dump(const char* where) const {
#if SHOW_SKIA_PATH
- SkDebugf("\n\nSkia Save Count %d:\n", pDriver->m_pCanvas->getSaveCount());
- pDriver->m_pCanvas->getClipStack()->dump();
- SkDebugf("Cache:\n");
+ printf("\n%s\nSkia Save Count %d:\n", where,
+ m_pDriver->m_pCanvas->getSaveCount());
+ m_pDriver->m_pCanvas->getClipStack()->dump();
+ printf("Cache:\n");
for (int index = 0; index < m_commands.count(); ++index) {
- SkDebugf("%s ", m_commandIndex == index ? "-->" : " ");
+ DumpPrefix(index);
switch (m_commands[index]) {
case Clip::kSave:
- SkDebugf("Save\n");
+ printf("Save %d\n", ++m_debugSaveCounter);
break;
case Clip::kPath:
m_clips[index].dump();
break;
default:
- SkDebugf("unknown\n");
+ printf("unknown\n");
}
}
- if (m_commandIndex == m_commands.count())
- SkDebugf("-->\n");
+ DumpEndPrefix();
#endif // SHOW_SKIA_PATH
+#ifdef SK_DEBUG
+ int skCanvasSaveCount = m_pDriver->m_pCanvas->getSaveCount();
+ int cacheSaveCount = 1;
+ SkASSERT(m_clipIndex <= m_commands.count());
+ for (int index = 0; index < m_clipIndex; ++index)
+ cacheSaveCount += Clip::kSave == m_commands[index];
+ SkASSERT(skCanvasSaveCount == cacheSaveCount);
+#endif
}
private:
@@ -1029,19 +1123,24 @@ class SkiaState {
CFX_GraphStateData m_clipState;
CFX_GraphStateData m_drawState;
CFX_Matrix m_clipMatrix;
+ CFX_SkiaDeviceDriver* m_pDriver;
CFX_Font* m_pFont;
FX_FLOAT m_fontSize;
uint32_t m_fillColor;
uint32_t m_strokeColor;
int m_blendType;
int m_commandIndex; // active position in clip command stack
- bool m_drawText;
- bool m_drawPath;
+ int m_drawIndex; // position of the pending path or text draw
+ int m_clipIndex; // position reflecting depth of canvas clip stacck
+ Accumulator m_type; // type of pending draw
+ bool m_fillFullCover;
bool m_fillPath;
bool m_groupKnockout;
bool m_debugDisable; // turn off cache for debugging
+#if SHOW_SKIA_PATH
+ mutable int m_debugSaveCounter;
+#endif
};
-#endif // _SKIA_SUPPORT_
// convert a stroking path to scanlines
void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint,
@@ -1115,9 +1214,7 @@ CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap,
: m_pBitmap(pBitmap),
m_pOriDevice(pOriDevice),
m_pRecorder(nullptr),
-#ifdef _SKIA_SUPPORT_
- m_pCache(new SkiaState),
-#endif
+ m_pCache(new SkiaState(this)),
#ifdef _SKIA_SUPPORT_PATHS_
m_pClipRgn(nullptr),
m_FillFlags(0),
@@ -1141,7 +1238,7 @@ CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(int size_x, int size_y)
: m_pBitmap(nullptr),
m_pOriDevice(nullptr),
m_pRecorder(new SkPictureRecorder),
- m_pCache(new SkiaState),
+ m_pCache(new SkiaState(this)),
m_bGroupKnockout(false) {
m_pRecorder->beginRecording(SkIntToScalar(size_x), SkIntToScalar(size_y));
m_pCanvas = m_pRecorder->getRecordingCanvas();
@@ -1151,7 +1248,7 @@ CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(SkPictureRecorder* recorder)
: m_pBitmap(nullptr),
m_pOriDevice(nullptr),
m_pRecorder(recorder),
- m_pCache(new SkiaState),
+ m_pCache(new SkiaState(this)),
m_bGroupKnockout(false) {
m_pCanvas = m_pRecorder->getRecordingCanvas();
}
@@ -1164,10 +1261,7 @@ CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() {
}
void CFX_SkiaDeviceDriver::Flush() {
-#ifdef _SKIA_SUPPORT_
- m_pCache->Flush(this);
- m_pCache->FlushCommands(this);
-#endif
+ m_pCache->Flush();
}
bool CFX_SkiaDeviceDriver::DrawDeviceText(int nChars,
@@ -1176,12 +1270,10 @@ bool CFX_SkiaDeviceDriver::DrawDeviceText(int nChars,
const CFX_Matrix* pObject2Device,
FX_FLOAT font_size,
uint32_t color) {
-#ifdef _SKIA_SUPPORT_
if (m_pCache->DrawText(nChars, pCharPos, pFont, pObject2Device, font_size,
- color, this)) {
+ color)) {
return true;
}
-#endif
sk_sp<SkTypeface> typeface(SkSafeRef(pFont->GetDeviceCache()));
SkPaint paint;
paint.setAntiAlias(true);
@@ -1269,9 +1361,7 @@ int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) const {
}
void CFX_SkiaDeviceDriver::SaveState() {
-#ifdef _SKIA_SUPPORT_
- if (!m_pCache->ClipSave(this))
-#endif
+ if (!m_pCache->ClipSave())
m_pCanvas->save();
#ifdef _SKIA_SUPPORT_PATHS_
@@ -1283,17 +1373,10 @@ void CFX_SkiaDeviceDriver::SaveState() {
}
void CFX_SkiaDeviceDriver::RestoreState(bool bKeepSaved) {
-#ifdef _SKIA_SUPPORT_
- if (!m_pCache->ClipRestore(this))
-#endif
+ if (!m_pCache->ClipRestore())
m_pCanvas->restore();
- if (bKeepSaved
-#ifdef _SKIA_SUPPORT_
- && !m_pCache->ClipSave(this)
-#endif
- ) {
+ if (bKeepSaved && !m_pCache->ClipSave())
m_pCanvas->save();
- }
#ifdef _SKIA_SUPPORT_PATHS_
m_pClipRgn.reset();
@@ -1346,10 +1429,7 @@ bool CFX_SkiaDeviceDriver::SetClip_PathFill(
) {
CFX_Matrix identity;
const CFX_Matrix* deviceMatrix = pObject2Device ? pObject2Device : &identity;
-#ifdef _SKIA_SUPPORT_
- if (m_pCache->SetClipFill(pPathData, deviceMatrix, fill_mode, this))
- return true;
-#endif // _SKIA_SUPPORT_
+ bool cached = m_pCache->SetClipFill(pPathData, deviceMatrix, fill_mode);
#ifdef _SKIA_SUPPORT_PATHS_
m_FillFlags = fill_mode;
@@ -1365,15 +1445,18 @@ bool CFX_SkiaDeviceDriver::SetClip_PathFill(
CFX_FloatRect(0, 0, (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH),
(FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
// note that PDF's y-axis goes up; Skia's y-axis goes down
- SkRect skClipRect =
- SkRect::MakeLTRB(rectf.left, rectf.bottom, rectf.right, rectf.top);
- DebugDrawSkiaClipRect(m_pCanvas, skClipRect);
- m_pCanvas->clipRect(skClipRect, SkCanvas::kIntersect_Op, true);
+ if (!cached) {
+ SkRect skClipRect =
+ SkRect::MakeLTRB(rectf.left, rectf.bottom, rectf.right, rectf.top);
+ DebugDrawSkiaClipRect(m_pCanvas, skClipRect);
+ m_pCanvas->clipRect(skClipRect, SkCanvas::kIntersect_Op, true);
+ }
#ifdef _SKIA_SUPPORT_PATHS_
FX_RECT rect = rectf.GetOuterRect();
m_pClipRgn->IntersectRect(rect);
#endif // _SKIA_SUPPORT_PATHS_
+ DebugShowCanvasClip(m_pCanvas);
return true;
}
}
@@ -1384,13 +1467,16 @@ bool CFX_SkiaDeviceDriver::SetClip_PathFill(
SkMatrix skMatrix = ToSkMatrix(*deviceMatrix);
skClipPath.transform(skMatrix);
DebugShowSkiaPath(skClipPath);
- DebugDrawSkiaClipPath(m_pCanvas, skClipPath);
- m_pCanvas->clipPath(skClipPath, SkCanvas::kIntersect_Op, true);
+ if (!cached) {
+ DebugDrawSkiaClipPath(m_pCanvas, skClipPath);
+ m_pCanvas->clipPath(skClipPath, SkCanvas::kIntersect_Op, true);
+ }
#ifdef _SKIA_SUPPORT_PATHS_
FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH),
GetDeviceCaps(FXDC_PIXEL_HEIGHT));
SetClipMask(clipBox, skClipPath);
#endif // _SKIA_SUPPORT_PATHS_
+ DebugShowCanvasClip(m_pCanvas);
return true;
}
@@ -1399,10 +1485,7 @@ bool CFX_SkiaDeviceDriver::SetClip_PathStroke(
const CFX_Matrix* pObject2Device, // optional transformation
const CFX_GraphStateData* pGraphState // graphic state, for pen attributes
) {
-#ifdef _SKIA_SUPPORT_
- if (m_pCache->SetClipStroke(pPathData, pObject2Device, pGraphState, this))
- return true;
-#endif // _SKIA_SUPPORT_
+ bool cached = m_pCache->SetClipStroke(pPathData, pObject2Device, pGraphState);
#ifdef _SKIA_SUPPORT_PATHS_
if (!m_pClipRgn) {
@@ -1418,16 +1501,16 @@ bool CFX_SkiaDeviceDriver::SetClip_PathStroke(
SkPath dst_path;
skPaint.getFillPath(skPath, &dst_path);
dst_path.transform(skMatrix);
- DebugDrawSkiaClipPath(m_pCanvas, dst_path);
-#ifdef _SKIA_SUPPORT_
- m_pCanvas->clipPath(dst_path, SkCanvas::kIntersect_Op, true);
-#endif // _SKIA_SUPPORT_
-
+ if (!cached) {
+ DebugDrawSkiaClipPath(m_pCanvas, dst_path);
+ m_pCanvas->clipPath(dst_path, SkCanvas::kIntersect_Op, true);
+ }
#ifdef _SKIA_SUPPORT_PATHS_
FX_RECT clipBox(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH),
GetDeviceCaps(FXDC_PIXEL_HEIGHT));
SetClipMask(clipBox, dst_path);
#endif // _SKIA_SUPPORT_PATHS_
+ DebugShowCanvasClip(m_pCanvas);
return true;
}
@@ -1441,15 +1524,10 @@ bool CFX_SkiaDeviceDriver::DrawPath(
int blend_type) {
if (fill_mode & FX_ZEROAREA_FILL)
return true;
-#ifdef _SKIA_SUPPORT_
if (m_pCache->DrawPath(pPathData, pObject2Device, pGraphState, fill_color,
- stroke_color, fill_mode, blend_type, this)) {
+ stroke_color, fill_mode, blend_type)) {
return true;
}
-#endif
- SkIRect rect;
- rect.set(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH),
- GetDeviceCaps(FXDC_PIXEL_HEIGHT));
SkMatrix skMatrix;
if (pObject2Device)
skMatrix = ToSkMatrix(*pObject2Device);
@@ -1513,6 +1591,7 @@ bool CFX_SkiaDeviceDriver::DrawCosmeticLine(FX_FLOAT x1,
bool CFX_SkiaDeviceDriver::FillRectWithBlend(const FX_RECT* pRect,
uint32_t fill_color,
int blend_type) {
+ m_pCache->FlushForDraw();
SkPaint spaint;
spaint.setAntiAlias(true);
spaint.setColor(fill_color);
@@ -1530,6 +1609,7 @@ bool CFX_SkiaDeviceDriver::DrawShading(const CPDF_ShadingPattern* pPattern,
const FX_RECT& clip_rect,
int alpha,
bool bAlphaMode) {
+ m_pCache->FlushForDraw();
ShadingType shadingType = pPattern->GetShadingType();
if (kAxialShading != shadingType && kRadialShading != shadingType &&
kCoonsPatchMeshShading != shadingType) {
@@ -1724,6 +1804,7 @@ bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) {
if (!srcBuffer)
return true;
#ifdef _SKIA_SUPPORT_
+ m_pCache->FlushForDraw();
int srcWidth = m_pBitmap->GetWidth();
int srcHeight = m_pBitmap->GetHeight();
int srcRowBytes = srcWidth * sizeof(uint32_t);
@@ -1749,10 +1830,11 @@ bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) {
#endif // _SKIA_SUPPORT_
#ifdef _SKIA_SUPPORT_PATHS_
+ Flush();
m_pBitmap->UnPreMultiply();
FX_RECT rect(left, top, left + pBitmap->GetWidth(),
top + pBitmap->GetHeight());
- CFX_DIBitmap* pBack = nullptr;
+ std::unique_ptr<CFX_DIBitmap> pBack;
if (m_pOriDevice) {
pBack = m_pOriDevice->Clone(&rect);
if (!pBack)
@@ -1771,12 +1853,11 @@ bool CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap, int left, int top) {
top = std::min(top, 0);
if (m_bRgbByteOrder) {
RgbByteOrderTransferBitmap(pBitmap, 0, 0, rect.Width(), rect.Height(),
- pBack, left, top);
+ pBack.get(), left, top);
} else {
- bRet = pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(), pBack,
- left, top);
+ bRet = pBitmap->TransferBitmap(0, 0, rect.Width(), rect.Height(),
+ pBack.get(), left, top);
}
- delete pBack;
return bRet;
#endif // _SKIA_SUPPORT_PATHS_
}
@@ -1802,6 +1883,7 @@ bool CFX_SkiaDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap,
#endif // _SKIA_SUPPORT_
#ifdef _SKIA_SUPPORT_PATHS_
+ Flush();
if (pBitmap->IsAlphaMask()) {
return m_pBitmap->CompositeMask(
left, top, pSrcRect->Width(), pSrcRect->Height(), pBitmap, argb,
@@ -1824,6 +1906,7 @@ bool CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource,
uint32_t flags,
int blend_type) {
#ifdef _SKIA_SUPPORT_
+ m_pCache->FlushForDraw();
if (!m_pBitmap->GetBuffer())
return true;
CFX_Matrix m(dest_width, 0, 0, -dest_height, dest_left,
@@ -1846,6 +1929,7 @@ bool CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource,
FX_RECT rect(0, 0, dest_width, dest_height);
return SetDIBits(pSource, argb, &rect, dest_left, dest_top, blend_type);
}
+ Flush();
FX_RECT dest_rect(dest_left, dest_top, dest_left + dest_width,
dest_top + dest_height);
dest_rect.Normalize();
@@ -1871,6 +1955,7 @@ bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
void*& handle,
int blend_type) {
#ifdef _SKIA_SUPPORT_
+ m_pCache->FlushForDraw();
DebugValidate(m_pBitmap, m_pOriDevice);
SkColorTable* ct = nullptr;
std::unique_ptr<uint8_t, FxFreeDeleter> dst8Storage;
@@ -1912,6 +1997,7 @@ bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
#endif // _SKIA_SUPPORT_
#ifdef _SKIA_SUPPORT_PATHS_
+ Flush();
if (!m_pBitmap->GetBuffer())
return true;
m_pBitmap->UnPreMultiply();
@@ -1925,10 +2011,12 @@ bool CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
bool CFX_SkiaDeviceDriver::ContinueDIBits(void* handle, IFX_Pause* pPause) {
#ifdef _SKIA_SUPPORT_
+ m_pCache->FlushForDraw();
return false;
#endif // _SKIA_SUPPORT_
#ifdef _SKIA_SUPPORT_PATHS_
+ Flush();
if (!m_pBitmap->GetBuffer()) {
return true;
}
diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h
index 06b7be3d82..c83f9919e0 100644
--- a/core/fxge/skia/fx_skia_device.h
+++ b/core/fxge/skia/fx_skia_device.h
@@ -152,8 +152,9 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver {
const CFX_GraphStateData* pGraphState,
const SkMatrix& matrix);
void Clear(uint32_t color);
- void Flush();
+ void Flush() override;
SkPictureRecorder* GetRecorder() const { return m_pRecorder; }
+ void PreMultiply() { m_pBitmap->PreMultiply(); }
static void PreMultiply(CFX_DIBitmap* pDIBitmap);
SkCanvas* SkiaCanvas() { return m_pCanvas; }
void DebugVerifyBitmapIsPreMultiplied() const;
@@ -166,9 +167,7 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver {
CFX_DIBitmap* m_pOriDevice;
SkCanvas* m_pCanvas;
SkPictureRecorder* const m_pRecorder;
-#ifdef _SKIA_SUPPORT_
std::unique_ptr<SkiaState> m_pCache;
-#endif
#ifdef _SKIA_SUPPORT_PATHS_
std::unique_ptr<CFX_ClipRgn> m_pClipRgn;
std::vector<std::unique_ptr<CFX_ClipRgn>> m_StateStack;
@@ -177,6 +176,6 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver {
#endif
bool m_bGroupKnockout;
};
-#endif // defined(_SKIA_SUPPORT_)
+#endif // defined _SKIA_SUPPORT_ || defined _SKIA_SUPPORT_PATHS_
#endif // CORE_FXGE_SKIA_FX_SKIA_DEVICE_H_
diff --git a/fpdfsdk/fpdfformfill.cpp b/fpdfsdk/fpdfformfill.cpp
index 44204b766a..6b8cbaa59d 100644
--- a/fpdfsdk/fpdfformfill.cpp
+++ b/fpdfsdk/fpdfformfill.cpp
@@ -137,10 +137,11 @@ void FFLCommon(FPDF_FORMHANDLE hHandle,
pPageView->PageView_OnDraw(pDevice.get(), &matrix, &options);
#endif // PDF_ENABLE_XFA
-#ifdef _SKIA_SUPPORT_PATHS
+ pDevice->RestoreState(false);
+#ifdef _SKIA_SUPPORT_PATHS_
+ pDevice->Flush();
CFXBitmapFromFPDFBitmap(bitmap)->UnPreMultiply();
#endif
- pDevice->RestoreState(false);
delete options.m_pOCContext;
options.m_pOCContext = nullptr;
}
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp
index f0c269a312..fb87c838d4 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -720,6 +720,7 @@ DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
rotate, flags, true, nullptr);
#ifdef _SKIA_SUPPORT_PATHS_
+ pDevice->Flush();
pBitmap->UnPreMultiply();
#endif
pPage->SetRenderContext(nullptr);