OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 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 "SkCanvas.h" | 8 #include "SkCanvas.h" |
9 #include "SkDevice.h" | 9 #include "SkDevice.h" |
10 #include "SkForceLinking.h" | 10 #include "SkForceLinking.h" |
(...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
732 | 732 |
733 if (skobj->has_Group()) { | 733 if (skobj->has_Group()) { |
734 canvas->restore(); | 734 canvas->restore(); |
735 } | 735 } |
736 | 736 |
737 canvas->restore(); | 737 canvas->restore(); |
738 PdfOp_Q(pdfContext, canvas, NULL); | 738 PdfOp_Q(pdfContext, canvas, NULL); |
739 return kPartial_PdfResult; | 739 return kPartial_PdfResult; |
740 } | 740 } |
741 | 741 |
| 742 |
| 743 // TODO(edisonn): Extract a class like ObjWithStream |
| 744 static PdfResult doXObject_Pattern(PdfContext* pdfContext, SkCanvas* canvas, SkP
dfType1PatternDictionary* skobj) { |
| 745 if (!skobj || !skobj->hasStream()) { |
| 746 return kIgnoreError_PdfResult; |
| 747 } |
| 748 |
| 749 if (!skobj->has_BBox()) { |
| 750 return kIgnoreError_PdfResult; |
| 751 } |
| 752 |
| 753 PdfOp_q(pdfContext, canvas, NULL); |
| 754 |
| 755 canvas->save(); |
| 756 |
| 757 |
| 758 if (skobj->Resources(pdfContext->fPdfDoc)) { |
| 759 pdfContext->fGraphicsState.fResources = skobj->Resources(pdfContext->fPd
fDoc); |
| 760 } |
| 761 |
| 762 SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "Current matrix"); |
| 763 |
| 764 if (skobj->has_Matrix()) { |
| 765 pdfContext->fGraphicsState.fCTM.preConcat(skobj->Matrix(pdfContext->fPdf
Doc)); |
| 766 pdfContext->fGraphicsState.fMatrixTm = pdfContext->fGraphicsState.fCTM; |
| 767 pdfContext->fGraphicsState.fMatrixTlm = pdfContext->fGraphicsState.fCTM; |
| 768 // TODO(edisonn) reset matrixTm and matricTlm also? |
| 769 } |
| 770 |
| 771 SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "Total matrix"); |
| 772 |
| 773 canvas->setMatrix(pdfContext->fGraphicsState.fCTM); |
| 774 |
| 775 SkRect bbox = skobj->BBox(pdfContext->fPdfDoc); |
| 776 canvas->clipRect(bbox, SkRegion::kIntersect_Op, true); // TODO(edisonn): AA
from settings. |
| 777 |
| 778 // TODO(edisonn): iterate smart on the stream even if it is compressed, toke
nize it as we go. |
| 779 // For this PdfContentsTokenizer needs to be extended. |
| 780 |
| 781 SkPdfStream* stream = (SkPdfStream*)skobj; |
| 782 |
| 783 SkPdfNativeTokenizer* tokenizer = |
| 784 pdfContext->fPdfDoc->tokenizerOfStream(stream, pdfContext->fTmpPageA
llocator); |
| 785 if (tokenizer != NULL) { |
| 786 PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas); |
| 787 looper.loop(); |
| 788 delete tokenizer; |
| 789 } |
| 790 |
| 791 // TODO(edisonn): should we restore the variable stack at the same state? |
| 792 // There could be operands left, that could be consumed by a parent tokenize
r when we pop. |
| 793 |
| 794 canvas->restore(); |
| 795 PdfOp_Q(pdfContext, canvas, NULL); |
| 796 return kPartial_PdfResult; |
| 797 } |
| 798 |
| 799 |
742 //static PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const
SkPdfObject* obj) { | 800 //static PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const
SkPdfObject* obj) { |
743 // return kNYI_PdfResult; | 801 // return kNYI_PdfResult; |
744 //} | 802 //} |
745 | 803 |
746 PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObjec
t* skobj, SkRect bBox, SkMatrix matrix, double textSize) { | 804 PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObjec
t* skobj, SkRect bBox, SkMatrix matrix, double textSize) { |
747 if (!skobj || !skobj->hasStream()) { | 805 if (!skobj || !skobj->hasStream()) { |
748 return kIgnoreError_PdfResult; | 806 return kIgnoreError_PdfResult; |
749 } | 807 } |
750 | 808 |
751 PdfOp_q(pdfContext, canvas, NULL); | 809 PdfOp_q(pdfContext, canvas, NULL); |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
819 CheckRecursiveRendering checkRecursion(obj); | 877 CheckRecursiveRendering checkRecursion(obj); |
820 | 878 |
821 switch (pdfContext->fPdfDoc->mapper()->mapXObjectDictionary(obj)) | 879 switch (pdfContext->fPdfDoc->mapper()->mapXObjectDictionary(obj)) |
822 { | 880 { |
823 case kImageDictionary_SkPdfObjectType: | 881 case kImageDictionary_SkPdfObjectType: |
824 return doXObject_Image(pdfContext, canvas, (SkPdfImageDictionary*)ob
j); | 882 return doXObject_Image(pdfContext, canvas, (SkPdfImageDictionary*)ob
j); |
825 case kType1FormDictionary_SkPdfObjectType: | 883 case kType1FormDictionary_SkPdfObjectType: |
826 return doXObject_Form(pdfContext, canvas, (SkPdfType1FormDictionary*
)obj); | 884 return doXObject_Form(pdfContext, canvas, (SkPdfType1FormDictionary*
)obj); |
827 //case kObjectDictionaryXObjectPS_SkPdfObjectType: | 885 //case kObjectDictionaryXObjectPS_SkPdfObjectType: |
828 //return doXObject_PS(skxobj.asPS()); | 886 //return doXObject_PS(skxobj.asPS()); |
829 default: | 887 default: { |
830 return kIgnoreError_PdfResult; | 888 if (pdfContext->fPdfDoc->mapper()->mapType1PatternDictionary(obj) !=
kNone_SkPdfObjectType) { |
| 889 SkPdfType1PatternDictionary* pattern = (SkPdfType1PatternDiction
ary*)obj; |
| 890 return doXObject_Pattern(pdfContext, canvas, pattern); |
| 891 } |
| 892 } |
831 } | 893 } |
| 894 return kIgnoreError_PdfResult; |
832 } | 895 } |
833 | 896 |
834 static PdfResult doPage(PdfContext* pdfContext, SkCanvas* canvas, SkPdfPageObjec
tDictionary* skobj) { | 897 static PdfResult doPage(PdfContext* pdfContext, SkCanvas* canvas, SkPdfPageObjec
tDictionary* skobj) { |
835 if (!skobj) { | 898 if (!skobj) { |
836 return kIgnoreError_PdfResult; | 899 return kIgnoreError_PdfResult; |
837 } | 900 } |
838 | 901 |
839 if (!skobj->isContentsAStream(pdfContext->fPdfDoc)) { | 902 if (!skobj->isContentsAStream(pdfContext->fPdfDoc)) { |
840 return kNYI_PdfResult; | 903 return kNYI_PdfResult; |
841 } | 904 } |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1158 } | 1221 } |
1159 | 1222 |
1160 canvas->setMatrix(pdfContext->fGraphicsState.fCTM); | 1223 canvas->setMatrix(pdfContext->fGraphicsState.fCTM); |
1161 | 1224 |
1162 SkPaint paint; | 1225 SkPaint paint; |
1163 | 1226 |
1164 SkPoint line[2]; | 1227 SkPoint line[2]; |
1165 if (fill && !stroke && path.isLine(line)) { | 1228 if (fill && !stroke && path.isLine(line)) { |
1166 paint.setStyle(SkPaint::kStroke_Style); | 1229 paint.setStyle(SkPaint::kStroke_Style); |
1167 | 1230 |
| 1231 // TODO(edisonn): implement this with patterns |
1168 pdfContext->fGraphicsState.applyGraphicsState(&paint, false); | 1232 pdfContext->fGraphicsState.applyGraphicsState(&paint, false); |
1169 paint.setStrokeWidth(SkDoubleToScalar(0)); | 1233 paint.setStrokeWidth(SkDoubleToScalar(0)); |
1170 | 1234 |
1171 canvas->drawPath(path, paint); | 1235 canvas->drawPath(path, paint); |
1172 } else { | 1236 } else { |
1173 if (fill) { | 1237 if (fill) { |
1174 paint.setStyle(SkPaint::kFill_Style); | 1238 if (strncmp((char*)pdfContext->fGraphicsState.fNonStroking.fColorSpa
ce.fBuffer, "Pattern", strlen("Pattern")) == 0 && |
1175 if (evenOdd) { | 1239 pdfContext->fGraphicsState.fNonStroking.fPattern != NULL) { |
1176 path.setFillType(SkPath::kEvenOdd_FillType); | 1240 |
| 1241 // TODO(edisonn): we can use a shader here, like imageshader to
draw fast. ultimately, |
| 1242 // if this is not possible, and we are in rasper mode, and the c
ells don't intersect, we could even have multiple cpus. |
| 1243 |
| 1244 canvas->save(); |
| 1245 PdfOp_q(pdfContext, canvas, NULL); |
| 1246 |
| 1247 if (evenOdd) { |
| 1248 path.setFillType(SkPath::kEvenOdd_FillType); |
| 1249 } |
| 1250 canvas->clipPath(path); |
| 1251 |
| 1252 if (pdfContext->fPdfDoc->mapper()->mapType1PatternDictionary(pdf
Context->fGraphicsState.fNonStroking.fPattern) != kNone_SkPdfObjectType) { |
| 1253 SkPdfType1PatternDictionary* pattern = (SkPdfType1PatternDic
tionary*)pdfContext->fGraphicsState.fNonStroking.fPattern; |
| 1254 |
| 1255 // TODO(edisonn): constants |
| 1256 // TODO(edisonn): colored |
| 1257 if (pattern->PaintType(pdfContext->fPdfDoc) == 1) { |
| 1258 int xStep = (int)pattern->XStep(pdfContext->fPdfDoc); |
| 1259 int yStep = (int)pattern->YStep(pdfContext->fPdfDoc); |
| 1260 |
| 1261 SkRect bounds = path.getBounds(); |
| 1262 SkScalar x; |
| 1263 SkScalar y; |
| 1264 |
| 1265 // TODO(edisonn): xstep and ystep can be negative, and w
e need to iterate in reverse |
| 1266 |
| 1267 y = bounds.top(); |
| 1268 int totalx = 0; |
| 1269 int totaly = 0; |
| 1270 while (y < bounds.bottom()) { |
| 1271 x = bounds.left(); |
| 1272 totalx = 0; |
| 1273 |
| 1274 while (x < bounds.right()) { |
| 1275 doXObject(pdfContext, canvas, pattern); |
| 1276 |
| 1277 pdfContext->fGraphicsState.fCTM.preTranslate(SkI
ntToScalar(xStep), SkIntToScalar(0)); |
| 1278 totalx += xStep; |
| 1279 x += SkIntToScalar(xStep); |
| 1280 } |
| 1281 pdfContext->fGraphicsState.fCTM.preTranslate(SkIntTo
Scalar(-totalx), SkIntToScalar(0)); |
| 1282 |
| 1283 pdfContext->fGraphicsState.fCTM.preTranslate(SkIntTo
Scalar(0), SkIntToScalar(-yStep)); |
| 1284 totaly += yStep; |
| 1285 y += SkIntToScalar(yStep); |
| 1286 } |
| 1287 pdfContext->fGraphicsState.fCTM.preTranslate(SkIntToScal
ar(0), SkIntToScalar(totaly)); |
| 1288 } |
| 1289 } |
| 1290 |
| 1291 // apply matrix |
| 1292 // get xstep, y step, bbox ... for cliping, and bos of the path |
| 1293 |
| 1294 PdfOp_Q(pdfContext, canvas, NULL); |
| 1295 canvas->restore(); |
| 1296 } else { |
| 1297 paint.setStyle(SkPaint::kFill_Style); |
| 1298 if (evenOdd) { |
| 1299 path.setFillType(SkPath::kEvenOdd_FillType); |
| 1300 } |
| 1301 |
| 1302 pdfContext->fGraphicsState.applyGraphicsState(&paint, false); |
| 1303 |
| 1304 canvas->drawPath(path, paint); |
1177 } | 1305 } |
1178 | |
1179 pdfContext->fGraphicsState.applyGraphicsState(&paint, false); | |
1180 | |
1181 canvas->drawPath(path, paint); | |
1182 } | 1306 } |
1183 | 1307 |
1184 if (stroke) { | 1308 if (stroke) { |
1185 paint.setStyle(SkPaint::kStroke_Style); | 1309 if (false && strncmp((char*)pdfContext->fGraphicsState.fNonStroking.
fColorSpace.fBuffer, "Pattern", strlen("Pattern")) == 0) { |
| 1310 // TODO(edisonn): implement Pattern for strokes |
| 1311 paint.setStyle(SkPaint::kStroke_Style); |
1186 | 1312 |
1187 pdfContext->fGraphicsState.applyGraphicsState(&paint, true); | 1313 paint.setColor(SK_ColorGREEN); |
1188 | 1314 |
1189 path.setFillType(SkPath::kWinding_FillType); // reset it, just in c
ase it messes up the stroke | 1315 path.setFillType(SkPath::kWinding_FillType); // reset it, just
in case it messes up the stroke |
1190 canvas->drawPath(path, paint); | 1316 canvas->drawPath(path, paint); |
| 1317 } else { |
| 1318 paint.setStyle(SkPaint::kStroke_Style); |
| 1319 |
| 1320 pdfContext->fGraphicsState.applyGraphicsState(&paint, true); |
| 1321 |
| 1322 path.setFillType(SkPath::kWinding_FillType); // reset it, just
in case it messes up the stroke |
| 1323 canvas->drawPath(path, paint); |
| 1324 } |
1191 } | 1325 } |
1192 } | 1326 } |
1193 | 1327 |
1194 pdfContext->fGraphicsState.fPath.reset(); | 1328 pdfContext->fGraphicsState.fPath.reset(); |
1195 // todo zoom ... other stuff ? | 1329 // todo zoom ... other stuff ? |
1196 | 1330 |
1197 if (pdfContext->fGraphicsState.fHasClipPathToApply) { | 1331 if (pdfContext->fGraphicsState.fHasClipPathToApply) { |
1198 #ifndef PDF_DEBUG_NO_CLIPING | 1332 #ifndef PDF_DEBUG_NO_CLIPING |
1199 canvas->clipPath(pdfContext->fGraphicsState.fClipPath, SkRegion::kInters
ect_Op, true); | 1333 canvas->clipPath(pdfContext->fGraphicsState.fClipPath, SkRegion::kInters
ect_Op, true); |
1200 #endif | 1334 #endif |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1452 | 1586 |
1453 static PdfResult PdfOp_sc(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoop
er** looper) { | 1587 static PdfResult PdfOp_sc(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoop
er** looper) { |
1454 return PdfOp_SC_sc(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStrok
ing); | 1588 return PdfOp_SC_sc(pdfContext, canvas, &pdfContext->fGraphicsState.fNonStrok
ing); |
1455 } | 1589 } |
1456 | 1590 |
1457 static PdfResult PdfOp_SCN_scn(PdfContext* pdfContext, SkCanvas* canvas, SkPdfCo
lorOperator* colorOperator) { | 1591 static PdfResult PdfOp_SCN_scn(PdfContext* pdfContext, SkCanvas* canvas, SkPdfCo
lorOperator* colorOperator) { |
1458 if (pdfContext->fObjectStack.top()->isName()) { | 1592 if (pdfContext->fObjectStack.top()->isName()) { |
1459 SkPdfObject* name = pdfContext->fObjectStack.top(); pdfContext->fObje
ctStack.pop(); | 1593 SkPdfObject* name = pdfContext->fObjectStack.top(); pdfContext->fObje
ctStack.pop(); |
1460 | 1594 |
1461 //Next, get the ExtGState Dictionary from the Resource Dictionary: | 1595 //Next, get the ExtGState Dictionary from the Resource Dictionary: |
1462 SkPdfDictionary* extGStateDictionary = pdfContext->fGraphicsState.fResou
rces->Pattern(pdfContext->fPdfDoc); | 1596 SkPdfDictionary* patternResources = pdfContext->fGraphicsState.fResource
s->Pattern(pdfContext->fPdfDoc); |
1463 | 1597 |
1464 if (extGStateDictionary == NULL) { | 1598 if (patternResources == NULL) { |
1465 #ifdef PDF_TRACE | 1599 #ifdef PDF_TRACE |
1466 printf("ExtGState is NULL!\n"); | 1600 printf("ExtGState is NULL!\n"); |
1467 #endif | 1601 #endif |
1468 return kIgnoreError_PdfResult; | 1602 return kIgnoreError_PdfResult; |
1469 } | 1603 } |
1470 | 1604 |
1471 /*SkPdfObject* value = */pdfContext->fPdfDoc->resolveReference(extGState
Dictionary->get(name)); | 1605 colorOperator->setPatternColorSpace(pdfContext->fPdfDoc->resolveReferenc
e(patternResources->get(name))); |
1472 } | 1606 } |
1473 | 1607 |
1474 // TODO(edisonn): SCN supports more color spaces than SCN. Read and implemen
t spec. | 1608 // TODO(edisonn): SCN supports more color spaces than SCN. Read and implemen
t spec. |
1475 PdfOp_SC_sc(pdfContext, canvas, colorOperator); | 1609 PdfOp_SC_sc(pdfContext, canvas, colorOperator); |
1476 | 1610 |
1477 return kPartial_PdfResult; | 1611 return kPartial_PdfResult; |
1478 } | 1612 } |
1479 | 1613 |
1480 static PdfResult PdfOp_SCN(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoo
per** looper) { | 1614 static PdfResult PdfOp_SCN(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLoo
per** looper) { |
1481 return PdfOp_SCN_scn(pdfContext, canvas, &pdfContext->fGraphicsState.fStroki
ng); | 1615 return PdfOp_SCN_scn(pdfContext, canvas, &pdfContext->fGraphicsState.fStroki
ng); |
(...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2255 PdfResult PdfInlineImageLooper::consumeToken(PdfToken& token) { | 2389 PdfResult PdfInlineImageLooper::consumeToken(PdfToken& token) { |
2256 SkASSERT(false); | 2390 SkASSERT(false); |
2257 return kIgnoreError_PdfResult; | 2391 return kIgnoreError_PdfResult; |
2258 } | 2392 } |
2259 | 2393 |
2260 void PdfInlineImageLooper::loop() { | 2394 void PdfInlineImageLooper::loop() { |
2261 doXObject_Image(fPdfContext, fCanvas, fTokenizer->readInlineImage()); | 2395 doXObject_Image(fPdfContext, fCanvas, fTokenizer->readInlineImage()); |
2262 } | 2396 } |
2263 | 2397 |
2264 PdfResult PdfInlineImageLooper::done() { | 2398 PdfResult PdfInlineImageLooper::done() { |
2265 | |
2266 // TODO(edisonn): long to short names | |
2267 // TODO(edisonn): set properties in a map | |
2268 // TODO(edisonn): extract bitmap stream, check if PoDoFo has public utilitie
s to uncompress | |
2269 // the stream. | |
2270 | |
2271 SkBitmap bitmap; | |
2272 setup_bitmap(&bitmap, 50, 50, SK_ColorRED); | |
2273 | |
2274 // TODO(edisonn): matrix use. | |
2275 // Draw dummy red square, to show the prezence of the inline image. | |
2276 fCanvas->drawBitmap(bitmap, | |
2277 SkDoubleToScalar(0), | |
2278 SkDoubleToScalar(0), | |
2279 NULL); | |
2280 return kNYI_PdfResult; | 2399 return kNYI_PdfResult; |
2281 } | 2400 } |
2282 | 2401 |
2283 PdfResult PdfCompatibilitySectionLooper::consumeToken(PdfToken& token) { | 2402 PdfResult PdfCompatibilitySectionLooper::consumeToken(PdfToken& token) { |
2284 return fParent->consumeToken(token); | 2403 return fParent->consumeToken(token); |
2285 } | 2404 } |
2286 | 2405 |
2287 void PdfCompatibilitySectionLooper::loop() { | 2406 void PdfCompatibilitySectionLooper::loop() { |
2288 // TODO(edisonn): save stacks position, or create a new stack? | 2407 // TODO(edisonn): save stacks position, or create a new stack? |
2289 // TODO(edisonn): what happens if we pop out more variables then when we sta
rted? | 2408 // TODO(edisonn): what happens if we pop out more variables then when we sta
rted? |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2453 | 2572 |
2454 rect = SkRect::MakeWH(width, height); | 2573 rect = SkRect::MakeWH(width, height); |
2455 | 2574 |
2456 setup_bitmap(output, (int)SkScalarToDouble(width), (int)SkScalarToDouble(hei
ght)); | 2575 setup_bitmap(output, (int)SkScalarToDouble(width), (int)SkScalarToDouble(hei
ght)); |
2457 | 2576 |
2458 SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (*output))); | 2577 SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (*output))); |
2459 SkCanvas canvas(device); | 2578 SkCanvas canvas(device); |
2460 | 2579 |
2461 return renderer.renderPage(page, &canvas, rect); | 2580 return renderer.renderPage(page, &canvas, rect); |
2462 } | 2581 } |
OLD | NEW |