From cf6bffb79f6e62d096908e6629daba5525728272 Mon Sep 17 00:00:00 2001 From: Cary Clark Date: Thu, 24 Mar 2016 10:23:13 -0400 Subject: fix windows build; add blend modes Use FreeType instead of Direct Write on Windows. Since PDFium currently uses the graphics engine to draw but not to measure, the graphics engine needs to always use FreeType to get consistent metrics. Add a translation from PDF's blend modes to Skia's xfer modes. Turn on subpixel positioning for text to get more precise glyph placement. Pass the alpha through to get proper bitmap transparency. Address earlier nits. R=dsinclair@chromium.org, tsepez@chromium.org, dsinclair Review URL: https://codereview.chromium.org/1812263002 . --- core/fxge/skia/fx_skia_device.cpp | 103 +++++++++++++++++++++++++++----------- core/fxge/skia/fx_skia_device.h | 4 +- skia/skia_library.gypi | 20 ++++---- third_party/third_party.gyp | 10 ++++ 4 files changed, 97 insertions(+), 40 deletions(-) diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp index a06eac80b4..f0c7d4e442 100644 --- a/core/fxge/skia/fx_skia_device.cpp +++ b/core/fxge/skia/fx_skia_device.cpp @@ -19,10 +19,12 @@ #include "third_party/skia/include/core/SkTypeface.h" #include "third_party/skia/include/effects/SkDashPathEffect.h" +namespace { + #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) { +void DebugShowSkiaPath(const SkPath& path) { #if SHOW_SKIA_PATH char buffer[4096]; sk_bzero(buffer, sizeof(buffer)); @@ -32,19 +34,19 @@ static void DebugShowSkiaPath(const SkPath& path) { #endif // SHOW_SKIA_PATH } -static void DebugShowCanvasMatrix(const SkCanvas* canvas) { +void DebugShowCanvasMatrix(const SkCanvas* canvas) { #if SHOW_SKIA_PATH SkMatrix matrix = canvas->getTotalMatrix(); SkScalar m[9]; matrix.get9(m); - printf("(%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]); + printf("(%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 } #if DRAW_SKIA_CLIP -static SkPaint DebugClipPaint() { +SkPaint DebugClipPaint() { SkPaint paint; paint.setAntiAlias(true); paint.setColor(SK_ColorGREEN); @@ -52,27 +54,27 @@ static SkPaint DebugClipPaint() { return paint; } -static void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) { +void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) { SkPaint paint = DebugClipPaint(); canvas->drawRect(rect, paint); } -static void DebugDrawSkiaClipPath(SkCanvas* canvas, const SkPath& path) { +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) {} +void DebugDrawSkiaClipRect(SkCanvas* canvas, const SkRect& rect) {} +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) { +SkPath BuildPath(const CFX_PathData* pPathData) { SkPath skPath; const CFX_PathData* pFPath = pPathData; int nPoints = pFPath->GetPointCount(); @@ -97,6 +99,59 @@ static SkPath BuildPath(const CFX_PathData* pPathData) { return skPath; } +SkMatrix ToSkMatrix(const CFX_Matrix& m) { + SkMatrix skMatrix; + skMatrix.setAll(m.a, m.b, m.e, m.c, m.d, m.f, 0, 0, 1); + return skMatrix; +} + +// use when pdf's y-axis points up insead of down +SkMatrix ToFlippedSkMatrix(const CFX_Matrix& m) { + SkMatrix skMatrix; + skMatrix.setAll(m.a, m.b, m.e, -m.c, -m.d, m.f, 0, 0, 1); + return skMatrix; +} + +SkXfermode::Mode GetSkiaBlendMode(int blend_type) { + switch (blend_type) { + case FXDIB_BLEND_MULTIPLY: + return SkXfermode::kMultiply_Mode; + case FXDIB_BLEND_SCREEN: + return SkXfermode::kScreen_Mode; + case FXDIB_BLEND_OVERLAY: + return SkXfermode::kOverlay_Mode; + case FXDIB_BLEND_DARKEN: + return SkXfermode::kDarken_Mode; + case FXDIB_BLEND_LIGHTEN: + return SkXfermode::kLighten_Mode; + case FXDIB_BLEND_COLORDODGE: + return SkXfermode::kColorDodge_Mode; + case FXDIB_BLEND_COLORBURN: + return SkXfermode::kColorBurn_Mode; + case FXDIB_BLEND_HARDLIGHT: + return SkXfermode::kHardLight_Mode; + case FXDIB_BLEND_SOFTLIGHT: + return SkXfermode::kSoftLight_Mode; + case FXDIB_BLEND_DIFFERENCE: + return SkXfermode::kDifference_Mode; + case FXDIB_BLEND_EXCLUSION: + return SkXfermode::kExclusion_Mode; + case FXDIB_BLEND_HUE: + return SkXfermode::kHue_Mode; + case FXDIB_BLEND_SATURATION: + return SkXfermode::kSaturation_Mode; + case FXDIB_BLEND_COLOR: + return SkXfermode::kColor_Mode; + case FXDIB_BLEND_LUMINOSITY: + return SkXfermode::kLuminosity_Mode; + case FXDIB_BLEND_NORMAL: + default: + return SkXfermode::kSrcOver_Mode; + } +} + +} // namespace + // convert a stroking path to scanlines void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, const CFX_GraphStateData* pGraphState, @@ -132,8 +187,9 @@ void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, inverse.set(SkMatrix::kMTransY, 0); SkVector deviceUnits[2] = {{0, 1}, {1, 0}}; inverse.mapPoints(deviceUnits, SK_ARRAY_COUNT(deviceUnits)); - FX_FLOAT width = SkTMax(pGraphState->m_LineWidth, - SkTMin(deviceUnits[0].length(), deviceUnits[1].length())); + FX_FLOAT width = + SkTMax(pGraphState->m_LineWidth, + SkTMin(deviceUnits[0].length(), deviceUnits[1].length())); if (pGraphState->m_DashArray) { int count = (pGraphState->m_DashCount + 1) / 2; SkScalar* intervals = FX_Alloc2D(SkScalar, count, sizeof(SkScalar)); @@ -150,9 +206,8 @@ void CFX_SkiaDeviceDriver::PaintStroke(SkPaint* spaint, intervals[i * 2] = on; intervals[i * 2 + 1] = off; } - spaint->setPathEffect(SkDashPathEffect::Create(intervals, count * 2, - pGraphState->m_DashPhase)) - ->unref(); + spaint->setPathEffect( + SkDashPathEffect::Make(intervals, count * 2, pGraphState->m_DashPhase)); } spaint->setStyle(SkPaint::kStroke_Style); spaint->setAntiAlias(true); @@ -203,19 +258,6 @@ CFX_SkiaDeviceDriver::~CFX_SkiaDeviceDriver() { delete m_pAggDriver; } -static SkMatrix ToSkMatrix(const CFX_Matrix& m) { - SkMatrix skMatrix; - skMatrix.setAll(m.a, m.b, m.e, m.c, m.d, m.f, 0, 0, 1); - return skMatrix; -} - -// use when pdf's y-axis points up insead of down -static SkMatrix ToFlippedSkMatrix(const CFX_Matrix& m) { - SkMatrix skMatrix; - skMatrix.setAll(m.a, m.b, m.e, -m.c, -m.d, m.f, 0, 0, 1); - return skMatrix; -} - FX_BOOL CFX_SkiaDeviceDriver::DrawDeviceText(int nChars, const FXTEXT_CHARPOS* pCharPos, CFX_Font* pFont, @@ -233,6 +275,7 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawDeviceText(int nChars, paint.setTypeface(typeface); paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); paint.setTextSize(font_size); + paint.setSubpixelText(true); m_pCanvas->save(); SkMatrix skMatrix = ToFlippedSkMatrix(*pObject2Device); m_pCanvas->concat(skMatrix); @@ -345,6 +388,7 @@ FX_BOOL CFX_SkiaDeviceDriver::DrawPath( SkPath skPath = BuildPath(pPathData); SkPaint spaint; spaint.setAntiAlias(true); + spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); m_pCanvas->save(); SkMatrix skMatrix = ToSkMatrix(*pObject2Device); m_pCanvas->concat(skMatrix); @@ -380,6 +424,7 @@ FX_BOOL CFX_SkiaDeviceDriver::FillRect(const FX_RECT* pRect, SkPaint spaint; spaint.setAntiAlias(true); spaint.setColor(fill_color); + spaint.setXfermodeMode(GetSkiaBlendMode(blend_type)); m_pCanvas->drawRect( SkRect::MakeLTRB(pRect->left, pRect->top, pRect->right, pRect->bottom), @@ -513,6 +558,8 @@ FX_BOOL CFX_SkiaDeviceDriver::StartDIBits(const CFX_DIBSource* pSource, SkPaint paint; paint.setAntiAlias(true); paint.setFilterQuality(kHigh_SkFilterQuality); + paint.setXfermodeMode(GetSkiaBlendMode(blend_type)); + paint.setAlpha(bitmap_alpha); m_pCanvas->drawBitmap(skBitmap, 0, 0, &paint); m_pCanvas->restore(); return TRUE; diff --git a/core/fxge/skia/fx_skia_device.h b/core/fxge/skia/fx_skia_device.h index 8a92f37e34..012e370717 100644 --- a/core/fxge/skia/fx_skia_device.h +++ b/core/fxge/skia/fx_skia_device.h @@ -129,7 +129,9 @@ class CFX_SkiaDeviceDriver : public IFX_RenderDeviceDriver { void* pIccTransform = NULL) override; virtual uint8_t* GetBuffer() const { return m_pAggDriver->GetBuffer(); } - void PaintStroke(SkPaint* spaint, const CFX_GraphStateData* pGraphState, const SkMatrix& matrix); + void PaintStroke(SkPaint* spaint, + const CFX_GraphStateData* pGraphState, + const SkMatrix& matrix); SkPictureRecorder* GetRecorder() const { return m_pRecorder; } private: diff --git a/skia/skia_library.gypi b/skia/skia_library.gypi index fea93a3abc..bd29a5a984 100644 --- a/skia/skia_library.gypi +++ b/skia/skia_library.gypi @@ -35,10 +35,6 @@ '../third_party/skia/src/ports/SkDiscardableMemory_none.cpp', - '../third_party/skia/src/fonts/SkFontMgr_indirect.cpp', - '../third_party/skia/src/ports/SkFontHost_FreeType.cpp', - - '../third_party/skia/src/ports/SkFontMgr_empty_factory.cpp', '../third_party/skia/src/fonts/SkFontMgr_indirect.cpp', '../third_party/skia/src/fonts/SkRemotableFontMgr.cpp', '../third_party/skia/src/ports/SkRemotableFontMgr_win_dw.cpp', @@ -52,7 +48,9 @@ "../third_party/skia/src/ports/SkFontMgr_android.cpp", "../third_party/skia/src/ports/SkFontMgr_android_factory.cpp", '../third_party/skia/src/ports/SkFontMgr_android_parser.cpp', - '../third_party/skia/src/ports/SkFontMgr_win_dw.cpp', + '../third_party/skia/src/ports/SkFontMgr_custom.cpp', + '../third_party/skia/src/ports/SkFontMgr_custom_empty_factory.cpp', + '../third_party/skia/src/ports/SkGlobalInitialization_default.cpp', '../third_party/skia/src/ports/SkMemory_malloc.cpp', '../third_party/skia/src/ports/SkOSFile_posix.cpp', @@ -79,7 +77,6 @@ '../third_party/skia/src/utils/SkMD5.cpp', '../third_party/skia/src/utils/SkMeshUtils.cpp', '../third_party/skia/src/utils/SkNinePatch.cpp', - '../third_party/skia/src/utils/SkOSFile.cpp', '../third_party/skia/src/utils/SkParsePath.cpp', #windows @@ -112,6 +109,8 @@ '../third_party/skia/src/sfnt', '../third_party/skia/src/utils', '../third_party/skia/src/lazy', + # TODO(dsinclair): Right way to use third_party.gyp:fx_freetype? + '../third_party/freetype/include', ], 'conditions': [ ['skia_support_gpu != 0', { @@ -144,6 +143,9 @@ # Keeping _win.cpp "../third_party/skia/src/utils/SkThreadUtils_pthread.cpp", ], + 'dependencies': [ + '../third_party/third_party.gyp:fx_freetype' + ], },{ 'sources!': [ # Keeping _pthread.cpp @@ -169,10 +171,6 @@ '-Wno-unused', '-Wno-unused-function', ], - # TODO(dsinclair): Right way to use third_party.gyp:fx_freetype? - 'include_dirs': [ - '../third_party/freetype/include', - ], }], [ 'OS=="win" or OS=="mac" or OS=="ios" or OS=="android"', { 'sources!': [ @@ -182,7 +180,7 @@ '../third_party/skia/src/fonts/SkFontMgr_fontconfig.cpp', ], }], - [ 'OS=="win" or OS=="mac" or OS=="ios"', { + [ 'OS=="mac" or OS=="ios"', { 'sources!': [ '../third_party/skia/src/ports/SkFontHost_FreeType.cpp', '../third_party/skia/src/ports/SkFontHost_FreeType_common.cpp', diff --git a/third_party/third_party.gyp b/third_party/third_party.gyp index 665de0a146..7fd1082454 100644 --- a/third_party/third_party.gyp +++ b/third_party/third_party.gyp @@ -5,6 +5,7 @@ { 'variables': { 'pdf_enable_xfa%': 0, # Set to 1 by standalone.gypi in standalone builds. + 'pdf_use_skia%': 0, }, 'target_defaults': { 'defines': [ @@ -80,6 +81,15 @@ 'freetype/src/truetype/truetype.c', 'freetype/src/type1/type1.c', ], + 'conditions': [ + ['pdf_use_skia==1', { + 'sources': [ + 'freetype/src/base/ftfntfmt.c', + 'freetype/src/base/ftfstype.c', + 'freetype/src/base/fttype1.c', + ], + }], + ], 'variables': { 'clang_warning_flags': [ # open_face_PS_from_sfnt_stream() and open_face_from_buffer() in -- cgit v1.2.3