Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Side by Side Diff: src/pdf/SkPDFDevice.cpp

Issue 1159763004: SkPDF: with opaque draws, treat SRC mode as SRC_OVER (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: 2015-05-26 (Tuesday) 12:06:19 EDT Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests/skpdf_opaquesrcmodetosrcover.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2011 Google Inc. 2 * Copyright 2011 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 7
8 #include "SkPDFDevice.h" 8 #include "SkPDFDevice.h"
9 9
10 #include "SkAnnotation.h" 10 #include "SkAnnotation.h"
(...skipping 19 matching lines...) Expand all
30 #include "SkString.h" 30 #include "SkString.h"
31 #include "SkSurface.h" 31 #include "SkSurface.h"
32 #include "SkTextFormatParams.h" 32 #include "SkTextFormatParams.h"
33 #include "SkTemplates.h" 33 #include "SkTemplates.h"
34 #include "SkTypefacePriv.h" 34 #include "SkTypefacePriv.h"
35 35
36 #define DPI_FOR_RASTER_SCALE_ONE 72 36 #define DPI_FOR_RASTER_SCALE_ONE 72
37 37
38 // Utility functions 38 // Utility functions
39 39
40 static void fix_paint_xfermode(SkPaint* paint) {
reed1 2015/05/26 16:28:23 "fix" is not very descriptive, if I'm trying to un
hal.canary 2015/05/26 18:24:19 Done.
41 SkXfermode::Mode mode = SkXfermode::kSrcOver_Mode;
42 if (paint->getXfermode() && paint->getXfermode()->asMode(&mode)) {
43 if (mode == SkXfermode::kSrc_Mode &&
44 paint->getAlpha() == SK_AlphaOPAQUE && !paint->getColorFilter() &&
45 !paint->getPathEffect() && !paint->getMaskFilter() &&
46 !paint->getRasterizer() && !paint->getImageFilter() &&
47 !paint->getLooper()) {
48 paint->setXfermodeMode(SkXfermode::kSrcOver_Mode);
49 }
50 }
51 }
52
40 static void emit_pdf_color(SkColor color, SkWStream* result) { 53 static void emit_pdf_color(SkColor color, SkWStream* result) {
41 SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere. 54 SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere.
42 SkScalar colorScale = SkScalarInvert(0xFF); 55 SkScalar colorScale = SkScalarInvert(0xFF);
43 SkPDFUtils::AppendScalar(SkColorGetR(color) * colorScale, result); 56 SkPDFUtils::AppendScalar(SkColorGetR(color) * colorScale, result);
44 result->writeText(" "); 57 result->writeText(" ");
45 SkPDFUtils::AppendScalar(SkColorGetG(color) * colorScale, result); 58 SkPDFUtils::AppendScalar(SkColorGetG(color) * colorScale, result);
46 result->writeText(" "); 59 result->writeText(" ");
47 SkPDFUtils::AppendScalar(SkColorGetB(color) * colorScale, result); 60 SkPDFUtils::AppendScalar(SkColorGetB(color) * colorScale, result);
48 result->writeText(" "); 61 result->writeText(" ");
49 } 62 }
(...skipping 699 matching lines...) Expand 10 before | Expand all | Expand 10 after
749 SkSafeUnref(fAnnotations); 762 SkSafeUnref(fAnnotations);
750 fNamedDestinations.deleteAll(); 763 fNamedDestinations.deleteAll();
751 764
752 if (clearFontUsage) { 765 if (clearFontUsage) {
753 fFontGlyphUsage->reset(); 766 fFontGlyphUsage->reset();
754 } 767 }
755 } 768 }
756 769
757 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) { 770 void SkPDFDevice::drawPaint(const SkDraw& d, const SkPaint& paint) {
758 SkPaint newPaint = paint; 771 SkPaint newPaint = paint;
772 fix_paint_xfermode(&newPaint);
773
759 newPaint.setStyle(SkPaint::kFill_Style); 774 newPaint.setStyle(SkPaint::kFill_Style);
760 ScopedContentEntry content(this, d, newPaint); 775 ScopedContentEntry content(this, d, newPaint);
761 internalDrawPaint(newPaint, content.entry()); 776 internalDrawPaint(newPaint, content.entry());
762 } 777 }
763 778
764 void SkPDFDevice::internalDrawPaint(const SkPaint& paint, 779 void SkPDFDevice::internalDrawPaint(const SkPaint& paint,
765 ContentEntry* contentEntry) { 780 ContentEntry* contentEntry) {
766 if (!contentEntry) { 781 if (!contentEntry) {
767 return; 782 return;
768 } 783 }
769 SkRect bbox = SkRect::MakeWH(SkIntToScalar(this->width()), 784 SkRect bbox = SkRect::MakeWH(SkIntToScalar(this->width()),
770 SkIntToScalar(this->height())); 785 SkIntToScalar(this->height()));
771 SkMatrix inverse; 786 SkMatrix inverse;
772 if (!contentEntry->fState.fMatrix.invert(&inverse)) { 787 if (!contentEntry->fState.fMatrix.invert(&inverse)) {
773 return; 788 return;
774 } 789 }
775 inverse.mapRect(&bbox); 790 inverse.mapRect(&bbox);
776 791
777 SkPDFUtils::AppendRectangle(bbox, &contentEntry->fContent); 792 SkPDFUtils::AppendRectangle(bbox, &contentEntry->fContent);
778 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, 793 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
779 &contentEntry->fContent); 794 &contentEntry->fContent);
780 } 795 }
781 796
782 void SkPDFDevice::drawPoints(const SkDraw& d, SkCanvas::PointMode mode, 797 void SkPDFDevice::drawPoints(const SkDraw& d,
783 size_t count, const SkPoint* points, 798 SkCanvas::PointMode mode,
784 const SkPaint& passedPaint) { 799 size_t count,
800 const SkPoint* points,
801 const SkPaint& srcPaint) {
802 SkPaint passedPaint = srcPaint;
803 fix_paint_xfermode(&passedPaint);
804
785 if (count == 0) { 805 if (count == 0) {
786 return; 806 return;
787 } 807 }
788 808
789 if (handlePointAnnotation(points, count, *d.fMatrix, passedPaint)) { 809 if (handlePointAnnotation(points, count, *d.fMatrix, passedPaint)) {
790 return; 810 return;
791 } 811 }
792 812
793 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath. 813 // SkDraw::drawPoints converts to multiple calls to fDevice->drawPath.
794 // We only use this when there's a path effect because of the overhead 814 // We only use this when there's a path effect because of the overhead
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
859 &content.entry()->fContent); 879 &content.entry()->fContent);
860 SkPDFUtils::ClosePath(&content.entry()->fContent); 880 SkPDFUtils::ClosePath(&content.entry()->fContent);
861 SkPDFUtils::StrokePath(&content.entry()->fContent); 881 SkPDFUtils::StrokePath(&content.entry()->fContent);
862 } 882 }
863 break; 883 break;
864 default: 884 default:
865 SkASSERT(false); 885 SkASSERT(false);
866 } 886 }
867 } 887 }
868 888
869 void SkPDFDevice::drawRect(const SkDraw& d, const SkRect& rect, 889 void SkPDFDevice::drawRect(const SkDraw& d,
870 const SkPaint& paint) { 890 const SkRect& rect,
891 const SkPaint& srcPaint) {
892 SkPaint paint = srcPaint;
893 fix_paint_xfermode(&paint);
871 SkRect r = rect; 894 SkRect r = rect;
872 r.sort(); 895 r.sort();
873 896
874 if (paint.getPathEffect()) { 897 if (paint.getPathEffect()) {
875 if (d.fClip->isEmpty()) { 898 if (d.fClip->isEmpty()) {
876 return; 899 return;
877 } 900 }
878 SkPath path; 901 SkPath path;
879 path.addRect(r); 902 path.addRect(r);
880 drawPath(d, path, paint, NULL, true); 903 drawPath(d, path, paint, NULL, true);
881 return; 904 return;
882 } 905 }
883 906
884 if (handleRectAnnotation(r, *d.fMatrix, paint)) { 907 if (handleRectAnnotation(r, *d.fMatrix, paint)) {
885 return; 908 return;
886 } 909 }
887 910
888 ScopedContentEntry content(this, d, paint); 911 ScopedContentEntry content(this, d, paint);
889 if (!content.entry()) { 912 if (!content.entry()) {
890 return; 913 return;
891 } 914 }
892 SkPDFUtils::AppendRectangle(r, &content.entry()->fContent); 915 SkPDFUtils::AppendRectangle(r, &content.entry()->fContent);
893 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType, 916 SkPDFUtils::PaintPath(paint.getStyle(), SkPath::kWinding_FillType,
894 &content.entry()->fContent); 917 &content.entry()->fContent);
895 } 918 }
896 919
897 void SkPDFDevice::drawRRect(const SkDraw& draw, const SkRRect& rrect, const SkPa int& paint) { 920 void SkPDFDevice::drawRRect(const SkDraw& draw,
921 const SkRRect& rrect,
922 const SkPaint& srcPaint) {
923 SkPaint paint = srcPaint;
924 fix_paint_xfermode(&paint);
898 SkPath path; 925 SkPath path;
899 path.addRRect(rrect); 926 path.addRRect(rrect);
900 this->drawPath(draw, path, paint, NULL, true); 927 this->drawPath(draw, path, paint, NULL, true);
901 } 928 }
902 929
903 void SkPDFDevice::drawOval(const SkDraw& draw, const SkRect& oval, const SkPaint & paint) { 930 void SkPDFDevice::drawOval(const SkDraw& draw,
931 const SkRect& oval,
932 const SkPaint& srcPaint) {
933 SkPaint paint = srcPaint;
934 fix_paint_xfermode(&paint);
904 SkPath path; 935 SkPath path;
905 path.addOval(oval); 936 path.addOval(oval);
906 this->drawPath(draw, path, paint, NULL, true); 937 this->drawPath(draw, path, paint, NULL, true);
907 } 938 }
908 939
909 void SkPDFDevice::drawPath(const SkDraw& d, const SkPath& origPath, 940 void SkPDFDevice::drawPath(const SkDraw& d,
910 const SkPaint& paint, const SkMatrix* prePathMatrix, 941 const SkPath& origPath,
942 const SkPaint& srcPaint,
943 const SkMatrix* prePathMatrix,
911 bool pathIsMutable) { 944 bool pathIsMutable) {
945 SkPaint paint = srcPaint;
946 fix_paint_xfermode(&paint);
912 SkPath modifiedPath; 947 SkPath modifiedPath;
913 SkPath* pathPtr = const_cast<SkPath*>(&origPath); 948 SkPath* pathPtr = const_cast<SkPath*>(&origPath);
914 949
915 SkMatrix matrix = *d.fMatrix; 950 SkMatrix matrix = *d.fMatrix;
916 if (prePathMatrix) { 951 if (prePathMatrix) {
917 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) { 952 if (paint.getPathEffect() || paint.getStyle() != SkPaint::kFill_Style) {
918 if (!pathIsMutable) { 953 if (!pathIsMutable) {
919 pathPtr = &modifiedPath; 954 pathPtr = &modifiedPath;
920 pathIsMutable = true; 955 pathIsMutable = true;
921 } 956 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
960 return; 995 return;
961 } 996 }
962 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(), 997 SkPDFUtils::EmitPath(*pathPtr, paint.getStyle(),
963 &content.entry()->fContent); 998 &content.entry()->fContent);
964 SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(), 999 SkPDFUtils::PaintPath(paint.getStyle(), pathPtr->getFillType(),
965 &content.entry()->fContent); 1000 &content.entry()->fContent);
966 } 1001 }
967 1002
968 void SkPDFDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap, 1003 void SkPDFDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
969 const SkRect* src, const SkRect& dst, 1004 const SkRect* src, const SkRect& dst,
970 const SkPaint& paint, 1005 const SkPaint& srcPaint,
971 SkCanvas::DrawBitmapRectFlags flags) { 1006 SkCanvas::DrawBitmapRectFlags flags) {
1007 SkPaint paint = srcPaint;
1008 if (bitmap.isOpaque()) {
1009 fix_paint_xfermode(&paint);
1010 }
1011
972 // TODO: this code path must be updated to respect the flags parameter 1012 // TODO: this code path must be updated to respect the flags parameter
973 SkMatrix matrix; 1013 SkMatrix matrix;
974 SkRect bitmapBounds, tmpSrc, tmpDst; 1014 SkRect bitmapBounds, tmpSrc, tmpDst;
975 SkBitmap tmpBitmap; 1015 SkBitmap tmpBitmap;
976 1016
977 bitmapBounds.isetWH(bitmap.width(), bitmap.height()); 1017 bitmapBounds.isetWH(bitmap.width(), bitmap.height());
978 1018
979 // Compute matrix from the two rectangles 1019 // Compute matrix from the two rectangles
980 if (src) { 1020 if (src) {
981 tmpSrc = *src; 1021 tmpSrc = *src;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1016 dy = SkIntToScalar(srcIR.fTop); 1056 dy = SkIntToScalar(srcIR.fTop);
1017 } 1057 }
1018 if (dx || dy) { 1058 if (dx || dy) {
1019 matrix.preTranslate(dx, dy); 1059 matrix.preTranslate(dx, dy);
1020 } 1060 }
1021 } 1061 }
1022 this->drawBitmap(draw, *bitmapPtr, matrix, paint); 1062 this->drawBitmap(draw, *bitmapPtr, matrix, paint);
1023 } 1063 }
1024 1064
1025 void SkPDFDevice::drawBitmap(const SkDraw& d, const SkBitmap& bitmap, 1065 void SkPDFDevice::drawBitmap(const SkDraw& d, const SkBitmap& bitmap,
1026 const SkMatrix& matrix, const SkPaint& paint) { 1066 const SkMatrix& matrix, const SkPaint& srcPaint) {
1067 SkPaint paint = srcPaint;
1068 if (bitmap.isOpaque()) {
1069 fix_paint_xfermode(&paint);
1070 }
1071
1027 if (d.fClip->isEmpty()) { 1072 if (d.fClip->isEmpty()) {
1028 return; 1073 return;
1029 } 1074 }
1030 1075
1031 SkMatrix transform = matrix; 1076 SkMatrix transform = matrix;
1032 transform.postConcat(*d.fMatrix); 1077 transform.postConcat(*d.fMatrix);
1033 this->internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, NULL, 1078 this->internalDrawBitmap(transform, d.fClipStack, *d.fClip, bitmap, NULL,
1034 paint); 1079 paint);
1035 } 1080 }
1036 1081
1037 void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap, 1082 void SkPDFDevice::drawSprite(const SkDraw& d, const SkBitmap& bitmap,
1038 int x, int y, const SkPaint& paint) { 1083 int x, int y, const SkPaint& srcPaint) {
1084 SkPaint paint = srcPaint;
1085 if (bitmap.isOpaque()) {
1086 fix_paint_xfermode(&paint);
1087 }
1088
1039 if (d.fClip->isEmpty()) { 1089 if (d.fClip->isEmpty()) {
1040 return; 1090 return;
1041 } 1091 }
1042 1092
1043 SkMatrix matrix; 1093 SkMatrix matrix;
1044 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y)); 1094 matrix.setTranslate(SkIntToScalar(x), SkIntToScalar(y));
1045 this->internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL, 1095 this->internalDrawBitmap(matrix, d.fClipStack, *d.fClip, bitmap, NULL,
1046 paint); 1096 paint);
1047 } 1097 }
1048 1098
(...skipping 26 matching lines...) Expand all
1075 SkString tmp(len); 1125 SkString tmp(len);
1076 for (size_t i = 0; i < len; i++) { 1126 for (size_t i = 0; i < len; i++) {
1077 SkASSERT(0 == input[i] >> 8); 1127 SkASSERT(0 == input[i] >> 8);
1078 tmp[i] = static_cast<uint8_t>(input[i]); 1128 tmp[i] = static_cast<uint8_t>(input[i]);
1079 } 1129 }
1080 return SkPDFUtils::FormatString(tmp.c_str(), tmp.size()); 1130 return SkPDFUtils::FormatString(tmp.c_str(), tmp.size());
1081 } 1131 }
1082 } 1132 }
1083 1133
1084 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, 1134 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len,
1085 SkScalar x, SkScalar y, const SkPaint& paint) { 1135 SkScalar x, SkScalar y, const SkPaint& srcPaint) {
1136 SkPaint paint = srcPaint;
1137 fix_paint_xfermode(&paint);
1138
1086 NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false); 1139 NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
1087 if (paint.getMaskFilter() != NULL) { 1140 if (paint.getMaskFilter() != NULL) {
1088 // Don't pretend we support drawing MaskFilters, it makes for artifacts 1141 // Don't pretend we support drawing MaskFilters, it makes for artifacts
1089 // making text unreadable (e.g. same text twice when using CSS shadows). 1142 // making text unreadable (e.g. same text twice when using CSS shadows).
1090 return; 1143 return;
1091 } 1144 }
1092 SkPaint textPaint = calculate_text_paint(paint); 1145 SkPaint textPaint = calculate_text_paint(paint);
1093 ScopedContentEntry content(this, d, textPaint, true); 1146 ScopedContentEntry content(this, d, textPaint, true);
1094 if (!content.entry()) { 1147 if (!content.entry()) {
1095 return; 1148 return;
(...skipping 28 matching lines...) Expand all
1124 availableGlyphs, font->multiByteGlyphs()); 1177 availableGlyphs, font->multiByteGlyphs());
1125 content.entry()->fContent.writeText(encodedString.c_str()); 1178 content.entry()->fContent.writeText(encodedString.c_str());
1126 consumedGlyphCount += availableGlyphs; 1179 consumedGlyphCount += availableGlyphs;
1127 content.entry()->fContent.writeText(" Tj\n"); 1180 content.entry()->fContent.writeText(" Tj\n");
1128 } 1181 }
1129 content.entry()->fContent.writeText("ET\n"); 1182 content.entry()->fContent.writeText("ET\n");
1130 } 1183 }
1131 1184
1132 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, 1185 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len,
1133 const SkScalar pos[], int scalarsPerPos, 1186 const SkScalar pos[], int scalarsPerPos,
1134 const SkPoint& offset, const SkPaint& paint) { 1187 const SkPoint& offset, const SkPaint& srcPaint) {
1188 SkPaint paint = srcPaint;
1189 fix_paint_xfermode(&paint);
1190
1135 NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false); 1191 NOT_IMPLEMENTED(paint.getMaskFilter() != NULL, false);
1136 if (paint.getMaskFilter() != NULL) { 1192 if (paint.getMaskFilter() != NULL) {
1137 // Don't pretend we support drawing MaskFilters, it makes for artifacts 1193 // Don't pretend we support drawing MaskFilters, it makes for artifacts
1138 // making text unreadable (e.g. same text twice when using CSS shadows). 1194 // making text unreadable (e.g. same text twice when using CSS shadows).
1139 return; 1195 return;
1140 } 1196 }
1141 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); 1197 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos);
1142 SkPaint textPaint = calculate_text_paint(paint); 1198 SkPaint textPaint = calculate_text_paint(paint);
1143 ScopedContentEntry content(this, d, textPaint, true); 1199 ScopedContentEntry content(this, d, textPaint, true);
1144 if (!content.entry()) { 1200 if (!content.entry()) {
(...skipping 996 matching lines...) Expand 10 before | Expand all | Expand 10 after
2141 return; 2197 return;
2142 } 2198 }
2143 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap)); 2199 SkAutoTUnref<SkPDFObject> image(SkPDFBitmap::Create(fCanon, subsetBitmap));
2144 if (!image) { 2200 if (!image) {
2145 return; 2201 return;
2146 } 2202 }
2147 2203
2148 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), 2204 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()),
2149 &content.entry()->fContent); 2205 &content.entry()->fContent);
2150 } 2206 }
OLDNEW
« no previous file with comments | « no previous file | tests/skpdf_opaquesrcmodetosrcover.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698