1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/pdf/SkPDFDeviceFlattener.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,155 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkPDFDeviceFlattener.h" 1.12 + 1.13 +#include "SkDraw.h" 1.14 + 1.15 +static SkISize SkSizeToISize(const SkSize& size) { 1.16 + return SkISize::Make(SkScalarRoundToInt(size.width()), SkScalarRoundToInt(size.height())); 1.17 +} 1.18 + 1.19 +SkPDFDeviceFlattener::SkPDFDeviceFlattener(const SkSize& pageSize, const SkRect* trimBox) 1.20 + : SkPDFDevice(SkSizeToISize(pageSize), 1.21 + SkSizeToISize(pageSize), 1.22 + SkMatrix::I()) { 1.23 + // TODO(edisonn): store the trimbox on emit. 1.24 +} 1.25 + 1.26 +SkPDFDeviceFlattener::~SkPDFDeviceFlattener() { 1.27 +} 1.28 + 1.29 +static void flattenPaint(const SkDraw& d, SkPaint* paint) { 1.30 + if (paint->getShader()) { 1.31 + SkMatrix local = paint->getShader()->getLocalMatrix(); 1.32 + local.preConcat(*d.fMatrix); 1.33 + paint->getShader()->setLocalMatrix(local); 1.34 + } 1.35 +} 1.36 + 1.37 +void SkPDFDeviceFlattener::drawPoints(const SkDraw& d, SkCanvas::PointMode mode, 1.38 + size_t count, const SkPoint points[], 1.39 + const SkPaint& paint) { 1.40 + if (!mustFlatten(d)) { 1.41 + INHERITED::drawPoints(d, mode, count, points, paint); 1.42 + return; 1.43 + } 1.44 + 1.45 + SkPaint paintFlatten(paint); 1.46 + flattenPaint(d, &paintFlatten); 1.47 + 1.48 + SkPoint* flattenedPoints = SkNEW_ARRAY(SkPoint, count); 1.49 + d.fMatrix->mapPoints(flattenedPoints, points, SkToS32(count)); 1.50 + SkDraw draw(d); 1.51 + SkMatrix identity = SkMatrix::I(); 1.52 + draw.fMatrix = &identity; 1.53 + INHERITED::drawPoints(draw, mode, count, flattenedPoints, paintFlatten); 1.54 + SkDELETE_ARRAY(flattenedPoints); 1.55 +} 1.56 + 1.57 +void SkPDFDeviceFlattener::drawRect(const SkDraw& d, const SkRect& r, const SkPaint& paint) { 1.58 + if (!mustFlatten(d)) { 1.59 + INHERITED::drawRect(d, r, paint); 1.60 + return; 1.61 + } 1.62 + 1.63 + SkPath path; 1.64 + path.addRect(r); 1.65 + path.transform(*d.fMatrix); 1.66 + SkDraw draw(d); 1.67 + SkMatrix matrix = SkMatrix::I(); 1.68 + draw.fMatrix = &matrix; 1.69 + 1.70 + SkPaint paintFlatten(paint); 1.71 + flattenPaint(d, &paintFlatten); 1.72 + 1.73 + INHERITED::drawPath(draw, path, paintFlatten, NULL, true); 1.74 +} 1.75 + 1.76 +void SkPDFDeviceFlattener::drawPath(const SkDraw& d, const SkPath& origPath, 1.77 + const SkPaint& paint, const SkMatrix* prePathMatrix, 1.78 + bool pathIsMutable) { 1.79 + if (!mustFlatten(d) && !(prePathMatrix && prePathMatrix->hasPerspective())) { 1.80 + INHERITED::drawPath(d, origPath, paint, prePathMatrix, pathIsMutable); 1.81 + return; 1.82 + } 1.83 + 1.84 + SkPath* pathPtr = (SkPath*)&origPath; 1.85 + SkPath tmpPath; 1.86 + 1.87 + if (!pathIsMutable) { 1.88 + tmpPath = origPath; 1.89 + pathPtr = &tmpPath; 1.90 + } 1.91 + 1.92 + if (prePathMatrix) { 1.93 + pathPtr->transform(*prePathMatrix); 1.94 + } 1.95 + 1.96 + SkPaint paintFlatten(paint); 1.97 + flattenPaint(d, &paintFlatten); 1.98 + 1.99 + bool fill = paintFlatten.getFillPath(*pathPtr, &tmpPath); 1.100 + SkDEBUGCODE(pathPtr = (SkPath*)0x12345678); // Don't use pathPtr after this point. 1.101 + 1.102 + paintFlatten.setPathEffect(NULL); 1.103 + if (fill) { 1.104 + paintFlatten.setStyle(SkPaint::kFill_Style); 1.105 + } else { 1.106 + paintFlatten.setStyle(SkPaint::kStroke_Style); 1.107 + paintFlatten.setStrokeWidth(0); 1.108 + } 1.109 + 1.110 + tmpPath.transform(*d.fMatrix); 1.111 + 1.112 + SkDraw draw(d); 1.113 + SkMatrix matrix = SkMatrix::I(); 1.114 + draw.fMatrix = &matrix; 1.115 + 1.116 + INHERITED::drawPath(draw, tmpPath, paintFlatten, NULL, true); 1.117 +} 1.118 + 1.119 +void SkPDFDeviceFlattener::drawText(const SkDraw& d, const void* text, size_t len, 1.120 + SkScalar x, SkScalar y, const SkPaint& paint) { 1.121 + if (mustPathText(d, paint)) { 1.122 + d.drawText_asPaths((const char*)text, len, x, y, paint); 1.123 + return; 1.124 + } 1.125 + 1.126 + INHERITED::drawText(d, text, len, x, y, paint); 1.127 +} 1.128 + 1.129 +void SkPDFDeviceFlattener::drawPosText(const SkDraw& d, const void* text, size_t len, 1.130 + const SkScalar pos[], SkScalar constY, 1.131 + int scalarsPerPos, const SkPaint& paint) { 1.132 + if (mustPathText(d, paint)) { 1.133 + d.drawPosText_asPaths((const char*)text, len, pos, constY, scalarsPerPos, paint); 1.134 + return; 1.135 + } 1.136 + INHERITED::drawPosText(d, text, len, pos, constY,scalarsPerPos, paint); 1.137 +} 1.138 + 1.139 +void SkPDFDeviceFlattener::drawTextOnPath(const SkDraw& d, const void* text, size_t len, 1.140 + const SkPath& path, const SkMatrix* matrix, 1.141 + const SkPaint& paint) { 1.142 + if (mustPathText(d, paint) || (matrix && matrix->hasPerspective())) { 1.143 + d.drawTextOnPath((const char*)text, len, path, matrix, paint); 1.144 + return; 1.145 + } 1.146 + INHERITED::drawTextOnPath(d, text, len, path, matrix, paint); 1.147 +} 1.148 + 1.149 +bool SkPDFDeviceFlattener::mustFlatten(const SkDraw& d) const { 1.150 + // TODO(edisonn): testability, add flag to force return true. 1.151 + return d.fMatrix->hasPerspective(); 1.152 +} 1.153 + 1.154 +bool SkPDFDeviceFlattener::mustPathText(const SkDraw& d, const SkPaint&) { 1.155 + // TODO(edisonn): testability, add flag to force return true. 1.156 + // TODO(edisonn): TBD: How to flatten MaskFilter. 1.157 + return d.fMatrix->hasPerspective(); 1.158 +}