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

Side by Side Diff: experimental/PdfViewer/SkPdfRenderer.cpp

Issue 21288002: pdfviewer: (in progress, uploaded for backup): transparency groups - isolated and knockout flags (Closed) Base URL: http://skia.googlecode.com/svn/trunk/
Patch Set: Created 7 years, 4 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 | Annotate | Revision Log
OLDNEW
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 616 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 xfer.setXfermodeMode(SkXfermode::kSrcOut_Mode); // SkXfermode::kSdtOut_M ode 627 xfer.setXfermodeMode(SkXfermode::kSrcOut_Mode); // SkXfermode::kSdtOut_M ode
628 canvas->drawBitmapRect(sMask, dst, &xfer); 628 canvas->drawBitmapRect(sMask, dst, &xfer);
629 canvas->restore(); 629 canvas->restore();
630 } 630 }
631 631
632 canvas->restore(); 632 canvas->restore();
633 633
634 return kPartial_PdfResult; 634 return kPartial_PdfResult;
635 } 635 }
636 636
637 //TODO(edisonn): options for implementing isolation and knockout
638 // 1) emulate them (current solution)
639 // PRO: simple
640 // CON: will need to use readPixels, which means serious perf issues
641 // 2) Compile a plan for an array of matrixes, compose the result at the end
642 // PRO: might be faster then 1, no need to readPixels
643 // CON: multiple drawings (but on smaller areas), pay a price at loading pdf to compute a pdf draw plan
644 // on average, a load with empty draw is 100ms on all the skps we have, for complete sites
645 // 3) support them natively in SkCanvas
646 // PRO: simple
647 // CON: we would still need to use a form of readPixels anyway, so perf migh t be the same as 1)
648 // 4) compile a plan using pathops, and render once without any fancy rules with backdrop
649 // PRO: simple, fast
650 // CON: pathops must be bug free first + time to compute new paths
651 // pay a price at loading pdf to compute a pdf draw plan
652 // on average, a load with empty draw is 100ms on all the skps we have, for complete sites
653
654
655 // TODO(edisonn): draw plan from point! - list of draw ops of a point, like a tr ee!
656 // TODO(edisonn): Minimal PDF to draw some points - remove everything that it is not needed, save pdf uncompressed
657
658
659
660 static void doGroup_before(PdfContext* pdfContext, SkCanvas* canvas, SkRect bbox , SkPdfTransparencyGroupDictionary* tgroup, bool page) {
661 SkRect bboxOrig = bbox;
662 SkBitmap backdrop;
663 bool isolatedGroup = tgroup->I(pdfContext->fPdfDoc);
664 // bool knockoutGroup = tgroup->K(pdfContext->fPdfDoc);
665 bool hasPixels = false;
666 if (!isolatedGroup) {
667 // TODO(edisonn): if the rect is not mapable, the operation could be exp ensive, e.g.
668 // a diagonal long but small rect would require to save all the page
669 SkMatrix inverse;
670 if (pdfContext->fGraphicsState.fCTM.mapRect(&bbox) &&
671 canvas->getTotalMatrix().invert(&inverse) &&
672 inverse.mapRect(&bbox)) {
673 SkIRect area = SkIRect::MakeLTRB(SkScalarTruncToInt(bbox.left()),
674 SkScalarTruncToInt(bbox.top()),
675 SkScalarTruncToInt(bbox.right()) + 2,
676 SkScalarTruncToInt(bbox.bottom()) + 2);
677 SkBitmap dummy;
678 if (canvas->readPixels(area, &dummy)) {
679 hasPixels = true;
680 }
681 }
682 }
683 SkPaint paint;
684 pdfContext->fGraphicsState.applyGraphicsState(&paint, false);
685 canvas->saveLayer(&bboxOrig, isolatedGroup ? &paint : NULL);
686
687 if (hasPixels) {
688 canvas->drawBitmapRect(backdrop, bboxOrig, NULL);
689 }
690 }
691
692 //static void doGroup_after(PdfContext* pdfContext, SkCanvas* canvas, SkRect bbo x, SkPdfTransparencyGroupDictionary* tgroup) {
693 //}
694
637 static PdfResult doXObject_Form(PdfContext* pdfContext, SkCanvas* canvas, SkPdfT ype1FormDictionary* skobj) { 695 static PdfResult doXObject_Form(PdfContext* pdfContext, SkCanvas* canvas, SkPdfT ype1FormDictionary* skobj) {
638 if (!skobj || !skobj->hasStream()) { 696 if (!skobj || !skobj->hasStream()) {
639 return kIgnoreError_PdfResult; 697 return kIgnoreError_PdfResult;
640 } 698 }
641 699
700 if (!skobj->has_BBox()) {
701 return kIgnoreError_PdfResult;
702 }
703
642 PdfOp_q(pdfContext, canvas, NULL); 704 PdfOp_q(pdfContext, canvas, NULL);
643 705
644 706
645 707
646 canvas->save(); 708 canvas->save();
647 709
648 710
649 if (skobj->Resources(pdfContext->fPdfDoc)) { 711 if (skobj->Resources(pdfContext->fPdfDoc)) {
650 pdfContext->fGraphicsState.fResources = skobj->Resources(pdfContext->fPd fDoc); 712 pdfContext->fGraphicsState.fResources = skobj->Resources(pdfContext->fPd fDoc);
651 } 713 }
652 714
653 SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "Current matrix"); 715 SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "Current matrix");
654 716
655 if (skobj->has_Matrix()) { 717 if (skobj->has_Matrix()) {
656 pdfContext->fGraphicsState.fCTM.preConcat(skobj->Matrix(pdfContext->fPdf Doc)); 718 pdfContext->fGraphicsState.fCTM.preConcat(skobj->Matrix(pdfContext->fPdf Doc));
657 pdfContext->fGraphicsState.fMatrixTm = pdfContext->fGraphicsState.fCTM; 719 pdfContext->fGraphicsState.fMatrixTm = pdfContext->fGraphicsState.fCTM;
658 pdfContext->fGraphicsState.fMatrixTlm = pdfContext->fGraphicsState.fCTM; 720 pdfContext->fGraphicsState.fMatrixTlm = pdfContext->fGraphicsState.fCTM;
659 // TODO(edisonn) reset matrixTm and matricTlm also? 721 // TODO(edisonn) reset matrixTm and matricTlm also?
660 } 722 }
661 723
662 SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "Total matrix"); 724 SkTraceMatrix(pdfContext->fGraphicsState.fCTM, "Total matrix");
663 725
664 canvas->setMatrix(pdfContext->fGraphicsState.fCTM); 726 canvas->setMatrix(pdfContext->fGraphicsState.fCTM);
665 727
666 if (skobj->has_BBox()) { 728 SkRect bbox = skobj->BBox(pdfContext->fPdfDoc);
667 canvas->clipRect(skobj->BBox(pdfContext->fPdfDoc), SkRegion::kIntersect_ Op, true); // TODO(edisonn): AA from settings. 729 canvas->clipRect(bbox, SkRegion::kIntersect_Op, true); // TODO(edisonn): AA from settings.
668 }
669 730
670 // TODO(edisonn): iterate smart on the stream even if it is compressed, toke nize it as we go. 731 // TODO(edisonn): iterate smart on the stream even if it is compressed, toke nize it as we go.
671 // For this PdfContentsTokenizer needs to be extended. 732 // For this PdfContentsTokenizer needs to be extended.
672 733
673 // This is a group? 734 // This is a group?
674 if (skobj->has_Group()) { 735 if (skobj->has_Group()) {
675 //TransparencyGroupDictionary* ... 736 SkPdfTransparencyGroupDictionary* tgroup = skobj->Group(pdfContext->fPdf Doc);
737 doGroup_before(pdfContext, canvas, bbox, tgroup, false);
676 } 738 }
677 739
678 SkPdfStream* stream = (SkPdfStream*)skobj; 740 SkPdfStream* stream = (SkPdfStream*)skobj;
679 741
680 SkPdfNativeTokenizer* tokenizer = 742 SkPdfNativeTokenizer* tokenizer =
681 pdfContext->fPdfDoc->tokenizerOfStream(stream, pdfContext->fTmpPageA llocator); 743 pdfContext->fPdfDoc->tokenizerOfStream(stream, pdfContext->fTmpPageA llocator);
682 if (tokenizer != NULL) { 744 if (tokenizer != NULL) {
683 PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas); 745 PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas);
684 looper.loop(); 746 looper.loop();
685 delete tokenizer; 747 delete tokenizer;
686 } 748 }
687 749
688 // TODO(edisonn): should we restore the variable stack at the same state? 750 // TODO(edisonn): should we restore the variable stack at the same state?
689 // There could be operands left, that could be consumed by a parent tokenize r when we pop. 751 // There could be operands left, that could be consumed by a parent tokenize r when we pop.
752
753 if (skobj->has_Group()) {
754 canvas->restore();
755 }
756
690 canvas->restore(); 757 canvas->restore();
691 PdfOp_Q(pdfContext, canvas, NULL); 758 PdfOp_Q(pdfContext, canvas, NULL);
692 return kPartial_PdfResult; 759 return kPartial_PdfResult;
693 } 760 }
694 761
695 //static PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObject* obj) { 762 //static PdfResult doXObject_PS(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObject* obj) {
696 // return kNYI_PdfResult; 763 // return kNYI_PdfResult;
697 //} 764 //}
698 765
699 PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObjec t* skobj, SkRect bBox, SkMatrix matrix, double textSize) { 766 PdfResult doType3Char(PdfContext* pdfContext, SkCanvas* canvas, const SkPdfObjec t* skobj, SkRect bBox, SkMatrix matrix, double textSize) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
801 868
802 if (CheckRecursiveRendering::IsInRendering(skobj)) { 869 if (CheckRecursiveRendering::IsInRendering(skobj)) {
803 // Oops, corrupt PDF! 870 // Oops, corrupt PDF!
804 return kIgnoreError_PdfResult; 871 return kIgnoreError_PdfResult;
805 } 872 }
806 CheckRecursiveRendering checkRecursion(skobj); 873 CheckRecursiveRendering checkRecursion(skobj);
807 874
808 875
809 PdfOp_q(pdfContext, canvas, NULL); 876 PdfOp_q(pdfContext, canvas, NULL);
810 877
811 canvas->save();
812 878
813 if (skobj->Resources(pdfContext->fPdfDoc)) { 879 if (skobj->Resources(pdfContext->fPdfDoc)) {
814 pdfContext->fGraphicsState.fResources = skobj->Resources(pdfContext->fPd fDoc); 880 pdfContext->fGraphicsState.fResources = skobj->Resources(pdfContext->fPd fDoc);
815 } 881 }
816 882
817 // TODO(edisonn): refactor common path with doXObject() 883 // TODO(edisonn): MediaBox can be inherited!!!!
818 // This is a group? 884 SkRect bbox = skobj->MediaBox(pdfContext->fPdfDoc);
819 if (skobj->has_Group()) { 885 if (skobj->has_Group()) {
820 //TransparencyGroupDictionary* ... 886 SkPdfTransparencyGroupDictionary* tgroup = skobj->Group(pdfContext->fPdf Doc);
887 doGroup_before(pdfContext, canvas, bbox, tgroup, true);
888 } else {
889 canvas->save();
821 } 890 }
822 891
892
823 SkPdfNativeTokenizer* tokenizer = 893 SkPdfNativeTokenizer* tokenizer =
824 pdfContext->fPdfDoc->tokenizerOfStream(stream, pdfContext->fTmpPageA llocator); 894 pdfContext->fPdfDoc->tokenizerOfStream(stream, pdfContext->fTmpPageA llocator);
825 if (tokenizer != NULL) { 895 if (tokenizer != NULL) {
826 PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas); 896 PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas);
827 looper.loop(); 897 looper.loop();
828 delete tokenizer; 898 delete tokenizer;
829 } 899 }
830 900
831 // TODO(edisonn): should we restore the variable stack at the same state? 901 // TODO(edisonn): should we restore the variable stack at the same state?
832 // There could be operands left, that could be consumed by a parent tokenize r when we pop. 902 // There could be operands left, that could be consumed by a parent tokenize r when we pop.
(...skipping 742 matching lines...) Expand 10 before | Expand all | Expand 10 after
1575 // TODO(edisonn): alloc memory 1645 // TODO(edisonn): alloc memory
1576 return kIgnoreError_PdfResult; 1646 return kIgnoreError_PdfResult;
1577 } 1647 }
1578 for (int i = 0; i < cnt; i++) { 1648 for (int i = 0; i < cnt; i++) {
1579 if (!intervals->objAtAIndex(i)->isNumber()) { 1649 if (!intervals->objAtAIndex(i)->isNumber()) {
1580 // TODO(edisonn): report error/warning 1650 // TODO(edisonn): report error/warning
1581 return kIgnoreError_PdfResult; 1651 return kIgnoreError_PdfResult;
1582 } 1652 }
1583 } 1653 }
1584 1654
1585 pdfContext->fGraphicsState.fDashArrayLength = cnt;
1586 double total = 0; 1655 double total = 0;
1587 for (int i = 0 ; i < cnt; i++) { 1656 for (int i = 0 ; i < cnt; i++) {
1588 pdfContext->fGraphicsState.fDashArray[i] = intervals->objAtAIndex(i)->sc alarValue(); 1657 pdfContext->fGraphicsState.fDashArray[i] = intervals->objAtAIndex(i)->sc alarValue();
1589 total += pdfContext->fGraphicsState.fDashArray[i]; 1658 total += pdfContext->fGraphicsState.fDashArray[i];
1590 } 1659 }
1660 if (cnt & 1) {
1661 if (cnt == 1) {
1662 pdfContext->fGraphicsState.fDashArray[1] = pdfContext->fGraphicsStat e.fDashArray[0];
1663 cnt++;
1664 } else {
1665 // TODO(edisonn): report error/warning
1666 return kNYI_PdfResult;
1667 }
1668 }
1669 pdfContext->fGraphicsState.fDashArrayLength = cnt;
1591 pdfContext->fGraphicsState.fDashPhase = phase->scalarValue(); 1670 pdfContext->fGraphicsState.fDashPhase = phase->scalarValue();
1592 if (pdfContext->fGraphicsState.fDashPhase == 0) { 1671 if (pdfContext->fGraphicsState.fDashPhase == 0) {
1593 // other rules, changes? 1672 // other rules, changes?
1594 pdfContext->fGraphicsState.fDashPhase = total; 1673 pdfContext->fGraphicsState.fDashPhase = total;
1595 } 1674 }
1596 1675
1597 return kOK_PdfResult; 1676 return kOK_PdfResult;
1598 } 1677 }
1599 1678
1600 PdfResult skpdfGraphicsStateApplyD(PdfContext* pdfContext, SkPdfArray* dash) { 1679 PdfResult skpdfGraphicsStateApplyD(PdfContext* pdfContext, SkPdfArray* dash) {
(...skipping 783 matching lines...) Expand 10 before | Expand all | Expand 10 after
2384 2463
2385 rect = SkRect::MakeWH(width, height); 2464 rect = SkRect::MakeWH(width, height);
2386 2465
2387 setup_bitmap(output, (int)SkScalarToDouble(width), (int)SkScalarToDouble(hei ght)); 2466 setup_bitmap(output, (int)SkScalarToDouble(width), (int)SkScalarToDouble(hei ght));
2388 2467
2389 SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (*output))); 2468 SkAutoTUnref<SkDevice> device(SkNEW_ARGS(SkDevice, (*output)));
2390 SkCanvas canvas(device); 2469 SkCanvas canvas(device);
2391 2470
2392 return renderer.renderPage(page, &canvas, rect); 2471 return renderer.renderPage(page, &canvas, rect);
2393 } 2472 }
OLDNEW
« no previous file with comments | « experimental/PdfViewer/SkPdfBasics.cpp ('k') | experimental/PdfViewer/pdfparser/native/SkPdfNativeTokenizer.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698