Index: core/fxge/skia/fx_skia_device.cpp |
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp |
index 84db838807ee53fe77f3b4cf03e1c3152950b536..9c0ea07b3cb0d30d9cf2ba8bea70b884a168e0c7 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; |
} |