summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BUILD.gn8
-rw-r--r--core/fxge/agg/fx_agg_driver.h1
-rw-r--r--core/fxge/skia/fx_skia_device.cpp342
-rw-r--r--core/fxge/skia/fx_skia_device.h8
-rw-r--r--core/include/fxge/fx_ge.h6
-rw-r--r--fpdfsdk/fpdfformfill.cpp50
-rw-r--r--fpdfsdk/fpdfview.cpp22
-rw-r--r--public/fpdf_formfill.h12
-rw-r--r--public/fpdfview.h7
-rw-r--r--samples/BUILD.gn8
-rw-r--r--samples/pdfium_test.cc54
-rw-r--r--samples/samples.gyp6
12 files changed, 412 insertions, 112 deletions
diff --git a/BUILD.gn b/BUILD.gn
index d0de412f08..c9c5b016aa 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -617,12 +617,8 @@ static_library("fxge") {
]
if (pdf_use_skia) {
- sources = [
- "core/fxge/skia/fx_skia_device.cpp",
- ]
- deps = [
- "//skia",
- ]
+ sources += [ "core/src/fxge/skia/fx_skia_device.cpp" ]
+ deps += [ "//skia" ]
}
if (is_win) {
diff --git a/core/fxge/agg/fx_agg_driver.h b/core/fxge/agg/fx_agg_driver.h
index 3631016fea..ea4c36059b 100644
--- a/core/fxge/agg/fx_agg_driver.h
+++ b/core/fxge/agg/fx_agg_driver.h
@@ -134,6 +134,7 @@ class CFX_AggDeviceDriver : public IFX_RenderDeviceDriver {
void SetClipMask(agg::rasterizer_scanline_aa& rasterizer);
virtual uint8_t* GetBuffer() const;
+ const CFX_DIBitmap* GetBitmap() const { return m_pBitmap; }
private:
CFX_DIBitmap* m_pBitmap;
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 10eebe496c..acebf35eb8 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -10,10 +10,57 @@
#include "core/fxge/agg/fx_agg_driver.h"
#include "core/fxge/skia/fx_skia_device.h"
-#include "SkCanvas.h"
-#include "SkDashPathEffect.h"
-#include "SkPaint.h"
-#include "SkPath.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkColorPriv.h"
+#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "third_party/skia/include/core/SkStream.h"
+#include "third_party/skia/include/core/SkTypeface.h"
+#include "third_party/skia/include/effects/SkDashPathEffect.h"
+
+#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
+
+static 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\n", buffer);
+#endif // SHOW_SKIA_PATH
+}
+
+#if DRAW_SKIA_CLIP
+
+static SkPaint DebugClipPaint() {
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(SK_ColorGREEN);
+ paint.setStyle(SkPaint::kStroke_Style);
+ return paint;
+}
+
+static void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {
+ SkPaint paint = DebugClipPaint();
+ canvas->drawRect(rect, paint);
+}
+
+static void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) {
+ SkPaint paint = DebugClipPaint();
+ canvas->drawPath(path, paint);
+}
+
+#else // DRAW_SKIA_CLIP
+
+static void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {}
+static void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) {}
+
+#endif // DRAW_SKIA_CLIP
+
+#undef SHOW_SKIA_PATH
+#undef DRAW_SKIA_CLIP
static SkPath BuildPath(const CFX_PathData* pPathData,
const CFX_Matrix* pObject2Device) {
@@ -97,7 +144,7 @@ void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint,
->unref();
}
spaint->setStyle(SkPaint::kStroke_Style);
- spaint->setAntiAlias(TRUE);
+ spaint->setAntiAlias(true);
spaint->setStrokeWidth(width);
spaint->setStrokeMiter(pGraphState->m_MiterLimit);
spaint->setStrokeCap(cap);
@@ -108,24 +155,40 @@ CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(CFX_DIBitmap* pBitmap,
int dither_bits,
FX_BOOL bRgbByteOrder,
CFX_DIBitmap* pOriDevice,
- FX_BOOL bGroupKnockout) {
+ FX_BOOL bGroupKnockout)
+ : m_pRecorder(nullptr) {
m_pAggDriver = new CFX_AggDeviceDriver(pBitmap, dither_bits, bRgbByteOrder,
pOriDevice, bGroupKnockout);
SkBitmap skBitmap;
- const CFX_DIBitmap* bitmap = m_pAggDriver->m_pBitmap;
+ const CFX_DIBitmap* bitmap = m_pAggDriver->GetBitmap();
SkImageInfo imageInfo =
SkImageInfo::Make(bitmap->GetWidth(), bitmap->GetHeight(),
kN32_SkColorType, kOpaque_SkAlphaType);
skBitmap.installPixels(imageInfo, bitmap->GetBuffer(), bitmap->GetPitch(),
nullptr, /* to do : set color table */
nullptr, nullptr);
- m_canvas = new SkCanvas(skBitmap);
+ m_pCanvas = new SkCanvas(skBitmap);
+ m_ditherBits = dither_bits;
+}
+
+CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(int size_x, int size_y)
+ : m_pRecorder(new SkPictureRecorder) {
+ m_pAggDriver = nullptr;
+ m_pRecorder->beginRecording(SkIntToScalar(size_x), SkIntToScalar(size_y));
+ m_pCanvas = m_pRecorder->getRecordingCanvas();
+ m_ditherBits = 0;
+}
+
+CFX_SkiaDeviceDriver::CFX_SkiaDeviceDriver(SkPictureRecorder* recorder)
+ : m_pRecorder(recorder) {
+ m_pAggDriver = nullptr;
+ m_pCanvas = m_pRecorder->getRecordingCanvas();
+ m_ditherBits = 0;
}
CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() {
-#if 0 // TODO(caryclark) : mismatch on allocator ?
- delete m_canvas;
-#endif
+ if (!m_pRecorder)
+ delete m_pCanvas;
delete m_pAggDriver;
}
@@ -138,66 +201,97 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawDeviceText(int nChars,
FX_DWORD color,
int alpha_flag,
void* pIccTransform) {
- return m_pAggDriver->DrawDeviceText(nChars, pCharPos, pFont, pCache,
- pObject2Device, font_size, color,
- alpha_flag, pIccTransform);
+ SkAutoTUnref<SkTypeface> typeface(SkTypeface::CreateFromStream(
+ new SkMemoryStream(pFont->GetFontData(), pFont->GetSize())));
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setColor(color);
+ paint.setTypeface(typeface);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ paint.setTextSize(font_size);
+ m_pCanvas->save();
+ SkMatrix skMatrix;
+ const CFX_Matrix& m = *pObject2Device;
+ // note that PDF's y-axis goes up; Skia's y-axis goes down
+ skMatrix.setAll(m.a, m.b, m.e, -m.c, -m.d, m.f, 0, 0, 1);
+ m_pCanvas->concat(skMatrix);
+ for (int index = 0; index < nChars; ++index) {
+ const FXTEXT_CHARPOS& cp = pCharPos[index];
+ uint16_t glyph = (uint16_t)cp.m_GlyphIndex;
+ m_pCanvas->drawText(&glyph, 2, cp.m_OriginX, cp.m_OriginY, paint);
+ }
+ m_pCanvas->restore();
+ return TRUE;
}
int CFX_SkiaDeviceDriver::GetDeviceCaps(int caps_id) {
- return m_pAggDriver->GetDeviceCaps(caps_id);
+ switch (caps_id) {
+ case FXDC_DEVICE_CLASS:
+ return FXDC_DISPLAY;
+ case FXDC_PIXEL_WIDTH:
+ return m_pCanvas->imageInfo().width();
+ case FXDC_PIXEL_HEIGHT:
+ return m_pCanvas->imageInfo().height();
+ case FXDC_BITS_PIXEL:
+ return 32;
+ case FXDC_HORZ_SIZE:
+ case FXDC_VERT_SIZE:
+ return 0;
+ case FXDC_RENDER_CAPS:
+ return FXRC_GET_BITS | FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE |
+ FXRC_BLEND_MODE | FXRC_SOFT_CLIP | FXRC_ALPHA_OUTPUT;
+ case FXDC_DITHER_BITS:
+ return m_ditherBits;
+ }
+ return 0;
}
void CFX_SkiaDeviceDriver::SaveState() {
- m_canvas->save();
- m_pAggDriver->SaveState();
+ m_pCanvas->save();
+ if (m_pAggDriver)
+ m_pAggDriver->SaveState();
}
void CFX_SkiaDeviceDriver::RestoreState(FX_BOOL bKeepSaved) {
- m_pAggDriver->RestoreState(bKeepSaved);
- m_canvas->restore();
+ if (m_pAggDriver)
+ m_pAggDriver->RestoreState(bKeepSaved);
+ m_pCanvas->restore();
+ if (bKeepSaved)
+ m_pCanvas->save();
}
void CFX_SkiaDeviceDriver::SetClipMask(
agg::rasterizer_scanline_aa& rasterizer) {
- m_pAggDriver->SetClipMask(rasterizer);
+ if (m_pAggDriver)
+ m_pAggDriver->SetClipMask(rasterizer);
}
FX_BOOL CFX_SkiaDeviceDriver::SetClip_PathFill(
const CFX_PathData* pPathData, // path info
- const CFX_Matrix* pObject2Device, // optional transformation
+ const CFX_Matrix* pObject2Device, // flips object's y-axis
int fill_mode // fill mode, WINDING or ALTERNATE
) {
- if (!m_pAggDriver->m_pClipRgn) {
- m_pAggDriver->m_pClipRgn = new CFX_ClipRgn(
- GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
- }
-
if (pPathData->GetPointCount() == 5 || pPathData->GetPointCount() == 4) {
CFX_FloatRect rectf;
if (pPathData->IsRect(pObject2Device, &rectf)) {
rectf.Intersect(
CFX_FloatRect(0, 0, (FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_WIDTH),
(FX_FLOAT)GetDeviceCaps(FXDC_PIXEL_HEIGHT)));
- FX_RECT rect = rectf.GetOutterRect();
- m_pAggDriver->m_pClipRgn->IntersectRect(rect);
+ // 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);
return TRUE;
}
}
- SkPath clip = BuildPath(pPathData, pObject2Device);
- clip.setFillType((fill_mode & 3) == FXFILL_WINDING
- ? SkPath::kWinding_FillType
- : SkPath::kEvenOdd_FillType);
- const CFX_Matrix& m = *pObject2Device;
-#if 0
- // TODO(caryclark) : don't clip quite yet
- // need to understand how to save/restore to balance the clip
- printf("m:(%g,%g,%g) (%g,%g,%g)\n", m.a, m.b, m.c, m.d, m.e, m.f);
- clip.dump();
- SkMatrix skMatrix;
- skMatrix.setAll(m.a, m.b, m.c, m.d, m.e, m.f, 0, 0, 1);
- m_canvas->setMatrix(skMatrix);
- m_canvas->clipPath(clip, SkRegion::kReplace_Op);
-#endif
+ SkPath skClipPath = BuildPath(pPathData, pObject2Device);
+ skClipPath.setFillType((fill_mode & 3) == FXFILL_WINDING
+ ? SkPath::kWinding_FillType
+ : SkPath::kEvenOdd_FillType);
+ DebugShowSkiaPath(skClipPath);
+ DebugDrawSkiaClipPath(m_pCanvas, skClipPath);
+ m_pCanvas->clipPath(skClipPath);
return TRUE;
}
@@ -207,11 +301,6 @@ FX_BOOL CFX_SkiaDeviceDriver::SetClip_PathStroke(
const CFX_Matrix* pObject2Device, // optional transformation
const CFX_GraphStateData* pGraphState // graphic state, for pen attributes
) {
- if (!m_pAggDriver->m_pClipRgn) {
- m_pAggDriver->m_pClipRgn = new CFX_ClipRgn(
- GetDeviceCaps(FXDC_PIXEL_WIDTH), GetDeviceCaps(FXDC_PIXEL_HEIGHT));
- }
-
// build path data
SkPath skPath = BuildPath(pPathData, NULL);
skPath.setFillType(SkPath::kWinding_FillType);
@@ -220,15 +309,8 @@ FX_BOOL CFX_SkiaDeviceDriver::SetClip_PathStroke(
PaintStroke(&spaint, pGraphState);
SkPath dst_path;
spaint.getFillPath(skPath, &dst_path);
-#if 01
- SkMatrix skMatrix;
- const CFX_Matrix& m = *pObject2Device;
- skMatrix.setAll(m.a, m.b, m.c, m.d, m.e, m.f, 0, 0, 1);
- m_canvas->setMatrix(skMatrix);
- // TODO(caryclark) : don't clip quite yet
- // need to understand how to save/restore so that clip is later undone
- m_canvas->clipPath(dst_path, SkRegion::kReplace_Op);
-#endif
+ DebugDrawSkiaClipPath(m_pCanvas, dst_path);
+ m_pCanvas->clipPath(dst_path);
return TRUE;
}
@@ -239,8 +321,10 @@ FX_BOOL CFX_SkiaDeviceDriver::RenderRasterizer(
FX_BOOL bGroupKnockout,
int alpha_flag,
void* pIccTransform) {
- return m_pAggDriver->RenderRasterizer(
- rasterizer, color, bFullCover, bGroupKnockout, alpha_flag, pIccTransform);
+ return m_pAggDriver &&
+ m_pAggDriver->RenderRasterizer(rasterizer, color, bFullCover,
+ bGroupKnockout, alpha_flag,
+ pIccTransform);
}
FX_BOOL CFX_SkiaDeviceDriver::DrawPath(
@@ -253,14 +337,12 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawPath(
int alpha_flag,
void* pIccTransform,
int blend_type) {
- if (!GetBuffer())
- return TRUE;
SkIRect rect;
rect.set(0, 0, GetDeviceCaps(FXDC_PIXEL_WIDTH),
GetDeviceCaps(FXDC_PIXEL_HEIGHT));
SkPath skPath = BuildPath(pPathData, pObject2Device);
SkPaint spaint;
- spaint.setAntiAlias(TRUE);
+ spaint.setAntiAlias(true);
if ((fill_mode & 3) && fill_color) {
skPath.setFillType((fill_mode & 3) == FXFILL_WINDING
? SkPath::kWinding_FillType
@@ -268,7 +350,7 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawPath(
spaint.setStyle(SkPaint::kFill_Style);
spaint.setColor(fill_color);
- m_canvas->drawPath(skPath, spaint);
+ m_pCanvas->drawPath(skPath, spaint);
}
int stroke_alpha = FXGETFLAG_COLORTYPE(alpha_flag)
? FXGETFLAG_ALPHA_STROKE(alpha_flag)
@@ -277,7 +359,7 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawPath(
if (pGraphState && stroke_alpha) {
spaint.setColor(stroke_color);
PaintStroke(&spaint, pGraphState);
- m_canvas->drawPath(skPath, spaint);
+ m_pCanvas->drawPath(skPath, spaint);
}
return TRUE;
@@ -288,7 +370,8 @@ FX_BOOL CFX_SkiaDeviceDriver::SetPixel(int x,
FX_DWORD color,
int alpha_flag,
void* pIccTransform) {
- return m_pAggDriver->SetPixel(x, y, color, alpha_flag, pIccTransform);
+ return m_pAggDriver &&
+ m_pAggDriver->SetPixel(x, y, color, alpha_flag, pIccTransform);
}
FX_BOOL CFX_SkiaDeviceDriver::FillRect(const FX_RECT* pRect,
@@ -300,14 +383,20 @@ FX_BOOL CFX_SkiaDeviceDriver::FillRect(const FX_RECT* pRect,
spaint.setAntiAlias(true);
spaint.setColor(fill_color);
- m_canvas->drawRect(
+ m_pCanvas->drawRect(
SkRect::MakeLTRB(pRect->left, pRect->top, pRect->right, pRect->bottom),
spaint);
return TRUE;
}
FX_BOOL CFX_SkiaDeviceDriver::GetClipBox(FX_RECT* pRect) {
- return m_pAggDriver->GetClipBox(pRect);
+ // TODO(caryclark) call m_canvas->getClipDeviceBounds() instead
+ pRect->left = 0;
+ pRect->top = 0;
+ const SkImageInfo& canvasSize = m_pCanvas->imageInfo();
+ pRect->right = canvasSize.width();
+ pRect->bottom = canvasSize.height();
+ return TRUE;
}
FX_BOOL CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap,
@@ -315,7 +404,8 @@ FX_BOOL CFX_SkiaDeviceDriver::GetDIBits(CFX_DIBitmap* pBitmap,
int top,
void* pIccTransform,
FX_BOOL bDEdge) {
- return m_pAggDriver->GetDIBits(pBitmap, left, top, pIccTransform, bDEdge);
+ return m_pAggDriver &&
+ m_pAggDriver->GetDIBits(pBitmap, left, top, pIccTransform, bDEdge);
}
FX_BOOL CFX_SkiaDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap,
@@ -326,7 +416,8 @@ FX_BOOL CFX_SkiaDeviceDriver::SetDIBits(const CFX_DIBSource* pBitmap,
int blend_type,
int alpha_flag,
void* pIccTransform) {
- return m_pAggDriver->SetDIBits(pBitmap, argb, pSrcRect, left, top, blend_type,
+ return m_pAggDriver &&
+ m_pAggDriver->SetDIBits(pBitmap, argb, pSrcRect, left, top, blend_type,
alpha_flag, pIccTransform);
}
@@ -341,7 +432,8 @@ FX_BOOL CFX_SkiaDeviceDriver::StretchDIBits(const CFX_DIBSource* pSource,
int alpha_flag,
void* pIccTransform,
int blend_type) {
- return m_pAggDriver->StretchDIBits(pSource, argb, dest_left, dest_top,
+ return m_pAggDriver &&
+ m_pAggDriver->StretchDIBits(pSource, argb, dest_left, dest_top,
dest_width, dest_height, pClipRect, flags,
alpha_flag, pIccTransform, blend_type);
}
@@ -355,23 +447,98 @@ FX_BOOL CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource,
int alpha_flag,
void* pIccTransform,
int blend_type) {
- return m_pAggDriver->StartDIBits(pSource, bitmap_alpha, argb, pMatrix,
- render_flags, handle, alpha_flag,
- pIccTransform, blend_type);
+ SkColorType colorType;
+ void* buffer = pSource->GetBuffer();
+ std::unique_ptr<uint8_t, FxFreeDeleter> dst8Storage;
+ std::unique_ptr<uint32_t, FxFreeDeleter> dst32Storage;
+ int width = pSource->GetWidth();
+ int height = pSource->GetHeight();
+ int rowBytes = pSource->GetPitch();
+ switch (pSource->GetBPP()) {
+ case 1: {
+ dst8Storage.reset(FX_Alloc2D(uint8_t, width, height));
+ uint8_t* dst8Pixels = dst8Storage.get();
+ for (int y = 0; y < height; ++y) {
+ const uint8_t* srcRow =
+ static_cast<const uint8_t*>(buffer) + y * rowBytes;
+ uint8_t* dstRow = dst8Pixels + y * width;
+ for (int x = 0; x < width; ++x)
+ dstRow[x] = srcRow[x >> 3] & (1 << (~x & 0x07)) ? 0xFF : 0x00;
+ }
+ buffer = dst8Storage.get();
+ rowBytes = width;
+ colorType = SkColorType::kGray_8_SkColorType;
+ } break;
+ case 24: {
+ dst32Storage.reset(FX_Alloc2D(uint32_t, width, height));
+ uint32_t* dst32Pixels = dst32Storage.get();
+ for (int y = 0; y < height; ++y) {
+ const uint8_t* srcRow =
+ static_cast<const uint8_t*>(buffer) + y * rowBytes;
+ uint32_t* dstRow = dst32Pixels + y * width;
+ for (int x = 0; x < width; ++x)
+ dstRow[x] = SkPackARGB32(0xFF, srcRow[x * 3 + 2], srcRow[x * 3 + 1],
+ srcRow[x * 3 + 0]);
+ }
+ buffer = dst32Storage.get();
+ rowBytes = width * sizeof(uint32_t);
+ colorType = SkColorType::kN32_SkColorType;
+ } break;
+ case 32:
+ colorType = SkColorType::kN32_SkColorType;
+ break;
+ default:
+ colorType = SkColorType::kUnknown_SkColorType;
+ }
+ SkImageInfo imageInfo =
+ SkImageInfo::Make(width, height, colorType, kOpaque_SkAlphaType);
+ SkBitmap skBitmap;
+ skBitmap.installPixels(imageInfo, buffer, rowBytes,
+ nullptr, /* TODO(caryclark) : set color table */
+ nullptr, nullptr);
+ m_pCanvas->save();
+ bool landscape = !pMatrix->a;
+ if (landscape)
+ m_pCanvas->translate(m_pCanvas->imageInfo().width(), 0);
+ else
+ m_pCanvas->translate(pMatrix->e, pMatrix->f + pMatrix->d);
+
+ SkMatrix skMatrix = SkMatrix::MakeScale(1.f / width, 1.f / height);
+ m_pCanvas->concat(skMatrix);
+ const CFX_Matrix& m = *pMatrix;
+ // note that PDF's y-axis goes up; Skia's y-axis goes down
+ if (landscape)
+ skMatrix.setAll(-m.a, -m.b, m.e, m.c, m.d, m.f, 0, 0, 1);
+ else
+ skMatrix.setAll(m.a, m.b, 0, -m.c, -m.d, 0, 0, 0, 1);
+ m_pCanvas->concat(skMatrix);
+ SkPaint paint;
+ paint.setAntiAlias(true);
+ paint.setFilterQuality(kLow_SkFilterQuality);
+ m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint);
+ m_pCanvas->restore();
+ return TRUE;
}
FX_BOOL CFX_SkiaDeviceDriver::ContinueDIBits(void* pHandle, IFX_Pause* pPause) {
- return m_pAggDriver->ContinueDIBits(pHandle, pPause);
+ return m_pAggDriver && m_pAggDriver->ContinueDIBits(pHandle, pPause);
}
void CFX_SkiaDeviceDriver::CancelDIBits(void* pHandle) {
- m_pAggDriver->CancelDIBits(pHandle);
+ if (m_pAggDriver)
+ m_pAggDriver->CancelDIBits(pHandle);
}
CFX_SkiaDevice::CFX_SkiaDevice() {
m_bOwnedBitmap = FALSE;
}
+SkPictureRecorder* CFX_SkiaDevice::CreateRecorder(int size_x, int size_y) {
+ CFX_SkiaDeviceDriver* skDriver = new CFX_SkiaDeviceDriver(size_x, size_y);
+ SetDeviceDriver(skDriver);
+ return skDriver->GetRecorder();
+}
+
FX_BOOL CFX_SkiaDevice::Attach(CFX_DIBitmap* pBitmap,
int dither_bits,
FX_BOOL bRgbByteOrder,
@@ -380,9 +547,15 @@ FX_BOOL CFX_SkiaDevice::Attach(CFX_DIBitmap* pBitmap,
if (!pBitmap)
return FALSE;
SetBitmap(pBitmap);
- CFX_SkiaDeviceDriver* pDriver = new CFX_SkiaDeviceDriver(
- pBitmap, dither_bits, bRgbByteOrder, pOriDevice, bGroupKnockout);
- SetDeviceDriver(pDriver);
+ SetDeviceDriver(new CFX_SkiaDeviceDriver(pBitmap, dither_bits, bRgbByteOrder,
+ pOriDevice, bGroupKnockout));
+ return TRUE;
+}
+
+FX_BOOL CFX_SkiaDevice::AttachRecorder(SkPictureRecorder* recorder) {
+ if (!recorder)
+ return FALSE;
+ SetDeviceDriver(new CFX_SkiaDeviceDriver(recorder));
return TRUE;
}
@@ -409,17 +582,4 @@ CFX_SkiaDevice::~CFX_SkiaDevice() {
delete GetBitmap();
}
-#if 0
-#include <stdarg.h>
-#include <stdio.h>
-
-void SkDebugf(const char format[], ...) {
- va_list args;
- va_start(args, format);
- vfprintf(stderr, format, args);
- va_end(args);
-}
-
-#endif
-
#endif
diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h
index 1a36fbe85b..bb0a651263 100644
--- a/core/fxge/skia/fx_skia_device.h
+++ b/core/fxge/skia/fx_skia_device.h
@@ -10,6 +10,7 @@
class SkCanvas;
class SkPaint;
class SkPath;
+class SkPictureRecorder;
struct SkIRect;
class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver {
@@ -19,6 +20,8 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver {
FX_BOOL bRgbByteOrder,
CFX_DIBitmap* pOriDevice,
FX_BOOL bGroupKnockout);
+ CFX_SkiaDeviceDriver(SkPictureRecorder* recorder);
+ CFX_SkiaDeviceDriver(int size_x, int size_y);
~CFX_SkiaDeviceDriver() override;
/** Options */
@@ -139,10 +142,13 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver {
void SetClipMask(SkPath& skPath, SkPaint* spaint);
virtual uint8_t* GetBuffer() const { return m_pAggDriver->GetBuffer(); }
void PaintStroke(SkPaint* spaint, const CFX_GraphStateData* pGraphState);
+ SkPictureRecorder* GetRecorder() const { return m_pRecorder; }
private:
CFX_AggDeviceDriver* m_pAggDriver;
- SkCanvas* m_canvas;
+ SkCanvas* m_pCanvas;
+ SkPictureRecorder* const m_pRecorder;
+ int m_ditherBits;
};
#endif // defined(_SKIA_SUPPORT_)
diff --git a/core/include/fxge/fx_ge.h b/core/include/fxge/fx_ge.h
index 8a62f13d14..8e9df8c544 100644
--- a/core/include/fxge/fx_ge.h
+++ b/core/include/fxge/fx_ge.h
@@ -16,6 +16,7 @@ class CFX_FontCache;
class CFX_FaceCache;
class IFX_RenderDeviceDriver;
class CCodec_ModuleMgr;
+class SkPictureRecorder;
class CFX_GEModule {
public:
@@ -427,6 +428,7 @@ class CFX_FxgeDevice : public CFX_RenderDevice {
protected:
bool m_bOwnedBitmap;
};
+
class CFX_SkiaDevice : public CFX_RenderDevice {
public:
CFX_SkiaDevice();
@@ -438,12 +440,16 @@ class CFX_SkiaDevice : public CFX_RenderDevice {
CFX_DIBitmap* pOriDevice = NULL,
FX_BOOL bGroupKnockout = FALSE);
+ FX_BOOL AttachRecorder(SkPictureRecorder* recorder);
+
FX_BOOL Create(int width,
int height,
FXDIB_Format format,
int dither_bits = 0,
CFX_DIBitmap* pOriDevice = NULL);
+ SkPictureRecorder* CreateRecorder(int size_x, int size_y);
+
protected:
FX_BOOL m_bOwnedBitmap;
};
diff --git a/fpdfsdk/fpdfformfill.cpp b/fpdfsdk/fpdfformfill.cpp
index 31f5732ce5..b33e303db0 100644
--- a/fpdfsdk/fpdfformfill.cpp
+++ b/fpdfsdk/fpdfformfill.cpp
@@ -287,15 +287,16 @@ DLLEXPORT FPDF_BOOL STDCALL FORM_ForceToKillFocus(FPDF_FORMHANDLE hHandle) {
return pSDKDoc->KillFocusAnnot(0);
}
-DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
- FPDF_BITMAP bitmap,
- FPDF_PAGE page,
- int start_x,
- int start_y,
- int size_x,
- int size_y,
- int rotate,
- int flags) {
+static void FFLCommon(FPDF_FORMHANDLE hHandle,
+ FPDF_BITMAP bitmap,
+ FPDF_RECORDER recorder,
+ FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int flags) {
if (!hHandle)
return;
@@ -336,7 +337,8 @@ DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
FX_RECT clip(start_x, start_y, start_x + size_x, start_y + size_y);
#ifdef _SKIA_SUPPORT_
- std::unique_ptr<CFX_SkiaDevice> pDevice(new CFX_SkiaDevice);
+ std::unique_ptr<CFX_SkiaDevice> pDevice(new CFX_SkiaDevice());
+ pDevice->AttachRecorder(static_cast<SkPictureRecorder*>(recorder));
#else
std::unique_ptr<CFX_FxgeDevice> pDevice(new CFX_FxgeDevice);
#endif
@@ -374,6 +376,34 @@ DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
#endif // PDF_ENABLE_XFA
}
+DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
+ FPDF_BITMAP bitmap,
+ FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int flags) {
+ FFLCommon(hHandle, bitmap, nullptr, page, start_x, start_y, size_x, size_y,
+ rotate, flags);
+}
+
+#ifdef _SKIA_SUPPORT_
+DLLEXPORT void STDCALL FPDF_FFLRecord(FPDF_FORMHANDLE hHandle,
+ FPDF_RECORDER recorder,
+ FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int flags) {
+ FFLCommon(hHandle, nullptr, recorder, page, start_x, start_y, size_x, size_y,
+ rotate, flags);
+}
+#endif
+
#ifdef PDF_ENABLE_XFA
DLLEXPORT void STDCALL FPDF_Widget_Undo(FPDF_DOCUMENT document,
FPDF_WIDGET hWidget) {
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp
index 48fe0664a2..4630ac1e7e 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -645,7 +645,7 @@ DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
CRenderContext* pContext = new CRenderContext;
pPage->SetPrivateData((void*)1, pContext, DropContext);
#ifdef _SKIA_SUPPORT_
- pContext->m_pDevice = new CFX_SkiaDevice;
+ pContext->m_pDevice = new CFX_SkiaDevice();
if (flags & FPDF_REVERSE_BYTE_ORDER)
((CFX_SkiaDevice*)pContext->m_pDevice)
@@ -669,6 +669,26 @@ DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
pPage->RemovePrivateData((void*)1);
}
+#ifdef _SKIA_SUPPORT_
+DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page,
+ int size_x,
+ int size_y) {
+ CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
+ if (!pPage)
+ return nullptr;
+ std::unique_ptr<CRenderContext> pContext(new CRenderContext);
+ pPage->SetPrivateData((void*)1, pContext.get(), DropContext);
+ CFX_SkiaDevice* skDevice = new CFX_SkiaDevice();
+ FPDF_RECORDER recorder = skDevice->CreateRecorder(size_x, size_y);
+ pContext->m_pDevice = skDevice;
+
+ FPDF_RenderPage_Retail(pContext.get(), page, 0, 0, size_x, size_y, 0, 0, TRUE,
+ NULL);
+ pPage->RemovePrivateData((void*)1);
+ return recorder;
+}
+#endif
+
DLLEXPORT void STDCALL FPDF_ClosePage(FPDF_PAGE page) {
if (!page)
return;
diff --git a/public/fpdf_formfill.h b/public/fpdf_formfill.h
index 3aeccb92f3..81d6b691f0 100644
--- a/public/fpdf_formfill.h
+++ b/public/fpdf_formfill.h
@@ -1508,6 +1508,18 @@ DLLEXPORT void STDCALL FPDF_FFLDraw(FPDF_FORMHANDLE hHandle,
int rotate,
int flags);
+#ifdef _SKIA_SUPPORT_
+DLLEXPORT void STDCALL FPDF_FFLRecord(FPDF_FORMHANDLE hHandle,
+ FPDF_RECORDER recorder,
+ FPDF_PAGE page,
+ int start_x,
+ int start_y,
+ int size_x,
+ int size_y,
+ int rotate,
+ int flags);
+#endif
+
#ifdef PDF_ENABLE_XFA
/**
* Function: FPDF_HasXFAField
diff --git a/public/fpdfview.h b/public/fpdfview.h
index 68d0b1ad83..dad6299da5 100644
--- a/public/fpdfview.h
+++ b/public/fpdfview.h
@@ -37,6 +37,7 @@ typedef void* FPDF_PAGELINK;
typedef void* FPDF_PAGEOBJECT; // Page object(text, path, etc)
typedef void* FPDF_PAGERANGE;
typedef void* FPDF_PATH;
+typedef void* FPDF_RECORDER;
typedef void* FPDF_SCHHANDLE;
typedef void* FPDF_TEXTPAGE;
@@ -582,6 +583,12 @@ DLLEXPORT void STDCALL FPDF_RenderPageBitmap(FPDF_BITMAP bitmap,
int rotate,
int flags);
+#ifdef _SKIA_SUPPORT_
+DLLEXPORT FPDF_RECORDER STDCALL FPDF_RenderPageSkp(FPDF_PAGE page,
+ int size_x,
+ int size_y);
+#endif
+
// Function: FPDF_ClosePage
// Close a loaded PDF page.
// Parameters:
diff --git a/samples/BUILD.gn b/samples/BUILD.gn
index 9ff1bea4c1..5e300158c9 100644
--- a/samples/BUILD.gn
+++ b/samples/BUILD.gn
@@ -9,8 +9,8 @@ import("../pdfium.gni")
group("samples") {
testonly = true
deps = [
- ":pdfium_test",
":pdfium_diff",
+ ":pdfium_test",
]
}
@@ -26,6 +26,9 @@ config("pdfium_samples_config") {
if (pdf_enable_xfa) {
defines += [ "PDF_ENABLE_XFA" ]
}
+ if (pdf_use_skia) {
+ defines += [ "PDF_ENABLE_SKIA" ]
+ }
}
executable("pdfium_test") {
@@ -56,6 +59,9 @@ executable("pdfium_test") {
]
configs += [ "//v8:external_startup_data" ]
}
+ if (pdf_use_skia) {
+ deps += [ "//skia" ]
+ }
configs += [ ":pdfium_samples_config" ]
}
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc
index 656e041e36..2ca31b08e9 100644
--- a/samples/pdfium_test.cc
+++ b/samples/pdfium_test.cc
@@ -13,6 +13,10 @@
#include <utility>
#include <vector>
+#if defined PDF_ENABLE_SKIA && !defined _SKIA_SUPPORT_
+#define _SKIA_SUPPORT_
+#endif
+
#include "public/fpdf_dataavail.h"
#include "public/fpdf_edit.h"
#include "public/fpdf_ext.h"
@@ -31,6 +35,11 @@
#define snprintf _snprintf
#endif
+#ifdef PDF_ENABLE_SKIA
+#include "third_party/skia/include/core/SkPictureRecorder.h"
+#include "third_party/skia/include/core/SkStream.h"
+#endif
+
enum OutputFormat {
OUTPUT_NONE,
OUTPUT_PPM,
@@ -39,6 +48,9 @@ enum OutputFormat {
OUTPUT_BMP,
OUTPUT_EMF,
#endif
+#ifdef PDF_ENABLE_SKIA
+ OUTPUT_SKP,
+#endif
};
struct Options {
@@ -116,7 +128,7 @@ static void WritePng(const char* pdf_name, int num, const void* buffer_void,
filename, sizeof(filename), "%s.%d.png", pdf_name, num);
if (chars_formatted < 0 ||
static_cast<size_t>(chars_formatted) >= sizeof(filename)) {
- fprintf(stderr, "Filname %s is too long\n", filename);
+ fprintf(stderr, "Filename %s is too long\n", filename);
return;
}
@@ -195,6 +207,25 @@ void WriteEmf(FPDF_PAGE page, const char* pdf_name, int num) {
}
#endif
+#ifdef PDF_ENABLE_SKIA
+void WriteSkp(const char* pdf_name, int num, const void* recorder) {
+ char filename[256];
+ int chars_formatted =
+ snprintf(filename, sizeof(filename), "%s.%d.skp", pdf_name, num);
+
+ if (chars_formatted < 0 ||
+ static_cast<size_t>(chars_formatted) >= sizeof(filename)) {
+ fprintf(stderr, "Filename %s is too long\n", filename);
+ return;
+ }
+
+ SkPictureRecorder* r = (SkPictureRecorder*)recorder;
+ SkPicture* picture = r->endRecordingAsPicture();
+ SkFILEWStream wStream(filename);
+ picture->serialize(&wStream);
+}
+#endif
+
// These example JS platform callback handlers are entirely optional,
// and exist here to show the flow of information from a document back
// to the embedder.
@@ -319,6 +350,14 @@ bool ParseCommandLine(const std::vector<std::string>& args,
return false;
}
options->output_format = OUTPUT_PNG;
+#ifdef PDF_ENABLE_SKIA
+ } else if (cur_arg == "--skp") {
+ if (options->output_format != OUTPUT_NONE) {
+ fprintf(stderr, "Duplicate or conflicting --skp argument\n");
+ return false;
+ }
+ options->output_format = OUTPUT_SKP;
+#endif
} else if (cur_arg.size() > 11 &&
cur_arg.compare(0, 11, "--font-dir=") == 0) {
if (!options->font_directory.empty()) {
@@ -431,6 +470,14 @@ bool RenderPage(const std::string& name,
WritePpm(name.c_str(), page_index, buffer, stride, width, height);
break;
+#ifdef PDF_ENABLE_SKIA
+ case OUTPUT_SKP: {
+ std::unique_ptr<SkPictureRecorder> recorder(
+ (SkPictureRecorder*)FPDF_RenderPageSkp(page, width, height));
+ FPDF_FFLRecord(form, recorder.get(), page, 0, 0, width, height, 0, 0);
+ WriteSkp(name.c_str(), page_index, recorder.get());
+ } break;
+#endif
default:
break;
}
@@ -634,7 +681,10 @@ static const char usage_string[] =
" --emf - write page meta files <pdf-name>.<page-number>.emf\n"
#endif // _WIN32
" --png - write page images <pdf-name>.<page-number>.png\n"
- " --ppm - write page images <pdf-name>.<page-number>.ppm\n";
+#ifdef PDF_ENABLE_SKIA
+ " --skp - write page images <pdf-name>.<page-number>.skp\n"
+#endif
+ "";
int main(int argc, const char* argv[]) {
std::vector<std::string> args(argv, argv + argc);
diff --git a/samples/samples.gyp b/samples/samples.gyp
index 6f262d5a04..b345f1d2c3 100644
--- a/samples/samples.gyp
+++ b/samples/samples.gyp
@@ -66,6 +66,12 @@
'<(DEPTH)/v8/tools/gyp/v8.gyp:v8_libplatform',
],
}],
+ ['pdf_use_skia==1', {
+ 'defines': ['PDF_ENABLE_SKIA'],
+ 'dependencies': [
+ '<(DEPTH)/skia/skia.gyp:skia',
+ ],
+ }],
],
},
{