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

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

Issue 944643002: PDF: Now threadsafe! (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: formatting Created 5 years, 10 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
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 557 matching lines...) Expand 10 before | Expand all | Expand 10 after
568 568
569 SkBaseDevice* SkPDFDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) { 569 SkBaseDevice* SkPDFDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) {
570 // PDF does not support image filters, so render them on CPU. 570 // PDF does not support image filters, so render them on CPU.
571 // Note that this rendering is done at "screen" resolution (100dpi), not 571 // Note that this rendering is done at "screen" resolution (100dpi), not
572 // printer resolution. 572 // printer resolution.
573 // FIXME: It may be possible to express some filters natively using PDF 573 // FIXME: It may be possible to express some filters natively using PDF
574 // to improve quality and file size (http://skbug.com/3043) 574 // to improve quality and file size (http://skbug.com/3043)
575 if (kImageFilter_Usage == cinfo.fUsage) { 575 if (kImageFilter_Usage == cinfo.fUsage) {
576 return SkBitmapDevice::Create(cinfo.fInfo); 576 return SkBitmapDevice::Create(cinfo.fInfo);
577 } 577 }
578
579 SkMatrix initialTransform;
580 initialTransform.reset();
581 SkISize size = SkISize::Make(cinfo.fInfo.width(), cinfo.fInfo.height()); 578 SkISize size = SkISize::Make(cinfo.fInfo.width(), cinfo.fInfo.height());
582 return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform)); 579 return SkPDFDevice::Create(size, fRasterDpi, fCanon);
583 } 580 }
584 581
585 582
586 struct ContentEntry { 583 struct ContentEntry {
587 GraphicStateEntry fState; 584 GraphicStateEntry fState;
588 SkDynamicMemoryWStream fContent; 585 SkDynamicMemoryWStream fContent;
589 SkAutoTDelete<ContentEntry> fNext; 586 SkAutoTDelete<ContentEntry> fNext;
590 587
591 // If the stack is too deep we could get Stack Overflow. 588 // If the stack is too deep we could get Stack Overflow.
592 // So we manually destruct the object. 589 // So we manually destruct the object.
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
688 paint.getXfermode()->asMode(&fXfermode); 685 paint.getXfermode()->asMode(&fXfermode);
689 } 686 }
690 fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion, 687 fContentEntry = fDevice->setUpContentEntry(clipStack, clipRegion,
691 matrix, paint, hasText, 688 matrix, paint, hasText,
692 &fDstFormXObject); 689 &fDstFormXObject);
693 } 690 }
694 }; 691 };
695 692
696 //////////////////////////////////////////////////////////////////////////////// 693 ////////////////////////////////////////////////////////////////////////////////
697 694
698 static inline SkImageInfo make_content_info(const SkISize& contentSize, 695 SkPDFDevice::SkPDFDevice(SkISize pageSize,
699 const SkMatrix* initialTransform) { 696 SkScalar rasterDpi,
700 SkImageInfo info; 697 SkPDFCanon* canon,
701 if (initialTransform) { 698 bool flip)
702 // Compute the size of the drawing area.
703 SkVector drawingSize;
704 SkMatrix inverse;
705 drawingSize.set(SkIntToScalar(contentSize.fWidth),
706 SkIntToScalar(contentSize.fHeight));
707 if (!initialTransform->invert(&inverse)) {
708 // This shouldn't happen, initial transform should be invertible.
709 SkASSERT(false);
710 inverse.reset();
711 }
712 inverse.mapVectors(&drawingSize, 1);
713 SkISize size = SkSize::Make(drawingSize.fX, drawingSize.fY).toRound();
714 info = SkImageInfo::MakeUnknown(abs(size.fWidth), abs(size.fHeight));
715 } else {
716 info = SkImageInfo::MakeUnknown(abs(contentSize.fWidth),
717 abs(contentSize.fHeight));
718 }
719 return info;
720 }
721
722 // TODO(vandebo) change pageSize to SkSize.
723 SkPDFDevice::SkPDFDevice(const SkISize& pageSize, const SkISize& contentSize,
724 const SkMatrix& initialTransform)
725 : fPageSize(pageSize) 699 : fPageSize(pageSize)
726 , fContentSize(contentSize) 700 , fContentSize(pageSize)
701 , fExistingClipRegion(SkIRect::MakeSize(pageSize))
702 , fAnnotations(NULL)
703 , fResourceDict(NULL)
727 , fLastContentEntry(NULL) 704 , fLastContentEntry(NULL)
728 , fLastMarginContentEntry(NULL) 705 , fLastMarginContentEntry(NULL)
706 , fDrawingArea(kContent_DrawingArea)
729 , fClipStack(NULL) 707 , fClipStack(NULL)
708 , fFontGlyphUsage(SkNEW(SkPDFGlyphSetMap))
730 , fEncoder(NULL) 709 , fEncoder(NULL)
731 , fRasterDpi(72.0f) 710 , fRasterDpi(rasterDpi)
732 { 711 , fCanon(canon) {
733 const SkImageInfo info = make_content_info(contentSize, &initialTransform); 712 SkASSERT(pageSize.width() > 0);
734 713 SkASSERT(pageSize.height() > 0);
735 // Just report that PDF does not supports perspective in the 714 fLegacyBitmap.setInfo(
736 // initial transform. 715 SkImageInfo::MakeUnknown(pageSize.width(), pageSize.height()));
737 NOT_IMPLEMENTED(initialTransform.hasPerspective(), true); 716 if (flip) {
738 717 // Skia generally uses the top left as the origin but PDF
739 // Skia generally uses the top left as the origin but PDF natively has the 718 // natively has the origin at the bottom left. This matrix
740 // origin at the bottom left. This matrix corrects for that. But that only 719 // corrects for that. But that only needs to be done once, we
741 // needs to be done once, we don't do it when layering. 720 // don't do it when layering.
742 fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight)); 721 fInitialTransform.setTranslate(0, SkIntToScalar(pageSize.fHeight));
743 fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1); 722 fInitialTransform.preScale(SK_Scalar1, -SK_Scalar1);
744 fInitialTransform.preConcat(initialTransform); 723 } else {
745 fLegacyBitmap.setInfo(info); 724 fInitialTransform.setIdentity();
746 725 }
747 SkIRect existingClip = info.bounds();
748 fExistingClipRegion.setRect(existingClip);
749 this->init();
750 }
751
752 // TODO(vandebo) change layerSize to SkSize.
753 SkPDFDevice::SkPDFDevice(const SkISize& layerSize,
754 const SkClipStack& existingClipStack,
755 const SkRegion& existingClipRegion)
756 : fPageSize(layerSize)
757 , fContentSize(layerSize)
758 , fExistingClipStack(existingClipStack)
759 , fExistingClipRegion(existingClipRegion)
760 , fLastContentEntry(NULL)
761 , fLastMarginContentEntry(NULL)
762 , fClipStack(NULL)
763 , fEncoder(NULL)
764 , fRasterDpi(72.0f)
765 {
766 fInitialTransform.reset();
767 fLegacyBitmap.setInfo(make_content_info(layerSize, NULL));
768
769 this->init();
770 } 726 }
771 727
772 SkPDFDevice::~SkPDFDevice() { 728 SkPDFDevice::~SkPDFDevice() {
773 this->cleanUp(true); 729 this->cleanUp(true);
774 } 730 }
775 731
776 void SkPDFDevice::init() { 732 void SkPDFDevice::init() {
777 fAnnotations = NULL; 733 fAnnotations = NULL;
778 fResourceDict = NULL; 734 fResourceDict = NULL;
779 fContentEntries.free(); 735 fContentEntries.free();
780 fLastContentEntry = NULL; 736 fLastContentEntry = NULL;
781 fMarginContentEntries.free(); 737 fMarginContentEntries.free();
782 fLastMarginContentEntry = NULL; 738 fLastMarginContentEntry = NULL;
783 fDrawingArea = kContent_DrawingArea; 739 fDrawingArea = kContent_DrawingArea;
784 if (fFontGlyphUsage.get() == NULL) { 740 if (fFontGlyphUsage.get() == NULL) {
785 fFontGlyphUsage.reset(new SkPDFGlyphSetMap()); 741 fFontGlyphUsage.reset(SkNEW(SkPDFGlyphSetMap));
786 } 742 }
787 } 743 }
788 744
789 void SkPDFDevice::cleanUp(bool clearFontUsage) { 745 void SkPDFDevice::cleanUp(bool clearFontUsage) {
790 fGraphicStateResources.unrefAll(); 746 fGraphicStateResources.unrefAll();
791 fXObjectResources.unrefAll(); 747 fXObjectResources.unrefAll();
792 fFontResources.unrefAll(); 748 fFontResources.unrefAll();
793 fShaderResources.unrefAll(); 749 fShaderResources.unrefAll();
794 SkSafeUnref(fAnnotations); 750 SkSafeUnref(fAnnotations);
795 SkSafeUnref(fResourceDict); 751 SkSafeUnref(fResourceDict);
(...skipping 1138 matching lines...) Expand 10 before | Expand all | Expand 10 after
1934 // a pattern the size of the current clip. 1890 // a pattern the size of the current clip.
1935 SkIRect bounds = clipRegion.getBounds(); 1891 SkIRect bounds = clipRegion.getBounds();
1936 1892
1937 // We need to apply the initial transform to bounds in order to get 1893 // We need to apply the initial transform to bounds in order to get
1938 // bounds in a consistent coordinate system. 1894 // bounds in a consistent coordinate system.
1939 SkRect boundsTemp; 1895 SkRect boundsTemp;
1940 boundsTemp.set(bounds); 1896 boundsTemp.set(bounds);
1941 fInitialTransform.mapRect(&boundsTemp); 1897 fInitialTransform.mapRect(&boundsTemp);
1942 boundsTemp.roundOut(&bounds); 1898 boundsTemp.roundOut(&bounds);
1943 1899
1944 pdfShader.reset(SkPDFShader::GetPDFShader(*shader, transform, bounds, 1900 SkScalar rasterScale =
1945 SkIntToScalar(fRasterDpi) / DPI_FOR_RASTER_SCALE_ONE)); 1901 SkIntToScalar(fRasterDpi) / DPI_FOR_RASTER_SCALE_ONE;
1902 pdfShader.reset(SkPDFShader::GetPDFShader(fCanon, *shader, transform,
1903 bounds, rasterScale));
1946 1904
1947 if (pdfShader.get()) { 1905 if (pdfShader.get()) {
1948 // pdfShader has been canonicalized so we can directly compare 1906 // pdfShader has been canonicalized so we can directly compare
1949 // pointers. 1907 // pointers.
1950 int resourceIndex = fShaderResources.find(pdfShader.get()); 1908 int resourceIndex = fShaderResources.find(pdfShader.get());
1951 if (resourceIndex < 0) { 1909 if (resourceIndex < 0) {
1952 resourceIndex = fShaderResources.count(); 1910 resourceIndex = fShaderResources.count();
1953 fShaderResources.push(pdfShader.get()); 1911 fShaderResources.push(pdfShader.get());
1954 pdfShader.get()->ref(); 1912 pdfShader.get()->ref();
1955 } 1913 }
(...skipping 10 matching lines...) Expand all
1966 SkShader::kColor_GradientType) { 1924 SkShader::kColor_GradientType) {
1967 entry->fColor = SkColorSetA(gradientColor, 0xFF); 1925 entry->fColor = SkColorSetA(gradientColor, 0xFF);
1968 color = gradientColor; 1926 color = gradientColor;
1969 } 1927 }
1970 } 1928 }
1971 } 1929 }
1972 1930
1973 SkAutoTUnref<SkPDFGraphicState> newGraphicState; 1931 SkAutoTUnref<SkPDFGraphicState> newGraphicState;
1974 if (color == paint.getColor()) { 1932 if (color == paint.getColor()) {
1975 newGraphicState.reset( 1933 newGraphicState.reset(
1976 SkPDFGraphicState::GetGraphicStateForPaint(paint)); 1934 SkPDFGraphicState::GetGraphicStateForPaint(fCanon, paint));
1977 } else { 1935 } else {
1978 SkPaint newPaint = paint; 1936 SkPaint newPaint = paint;
1979 newPaint.setColor(color); 1937 newPaint.setColor(color);
1980 newGraphicState.reset( 1938 newGraphicState.reset(
1981 SkPDFGraphicState::GetGraphicStateForPaint(newPaint)); 1939 SkPDFGraphicState::GetGraphicStateForPaint(fCanon, newPaint));
1982 } 1940 }
1983 int resourceIndex = addGraphicStateResource(newGraphicState.get()); 1941 int resourceIndex = addGraphicStateResource(newGraphicState.get());
1984 entry->fGraphicStateIndex = resourceIndex; 1942 entry->fGraphicStateIndex = resourceIndex;
1985 1943
1986 if (hasText) { 1944 if (hasText) {
1987 entry->fTextScaleX = paint.getTextScaleX(); 1945 entry->fTextScaleX = paint.getTextScaleX();
1988 entry->fTextFill = paint.getStyle(); 1946 entry->fTextFill = paint.getStyle();
1989 } else { 1947 } else {
1990 entry->fTextScaleX = 0; 1948 entry->fTextScaleX = 0;
1991 } 1949 }
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
2027 SkPDFResourceDict::kFont_ResourceType, 1985 SkPDFResourceDict::kFont_ResourceType,
2028 fontIndex).c_str()); 1986 fontIndex).c_str());
2029 contentEntry->fContent.writeText(" "); 1987 contentEntry->fContent.writeText(" ");
2030 SkPDFScalar::Append(paint.getTextSize(), &contentEntry->fContent); 1988 SkPDFScalar::Append(paint.getTextSize(), &contentEntry->fContent);
2031 contentEntry->fContent.writeText(" Tf\n"); 1989 contentEntry->fContent.writeText(" Tf\n");
2032 contentEntry->fState.fFont = fFontResources[fontIndex]; 1990 contentEntry->fState.fFont = fFontResources[fontIndex];
2033 } 1991 }
2034 } 1992 }
2035 1993
2036 int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) { 1994 int SkPDFDevice::getFontResourceIndex(SkTypeface* typeface, uint16_t glyphID) {
2037 SkAutoTUnref<SkPDFFont> newFont(SkPDFFont::GetFontResource(typeface, 1995 SkAutoTUnref<SkPDFFont> newFont(
2038 glyphID)); 1996 SkPDFFont::GetFontResource(fCanon, typeface, glyphID));
2039 int resourceIndex = fFontResources.find(newFont.get()); 1997 int resourceIndex = fFontResources.find(newFont.get());
2040 if (resourceIndex < 0) { 1998 if (resourceIndex < 0) {
2041 resourceIndex = fFontResources.count(); 1999 resourceIndex = fFontResources.count();
2042 fFontResources.push(newFont.get()); 2000 fFontResources.push(newFont.get());
2043 newFont.get()->ref(); 2001 newFont.get()->ref();
2044 } 2002 }
2045 return resourceIndex; 2003 return resourceIndex;
2046 } 2004 }
2047 2005
2048 void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix, 2006 void SkPDFDevice::internalDrawBitmap(const SkMatrix& origMatrix,
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after
2171 shape.addRect(SkRect::MakeWH(SkIntToScalar(subset.width()), 2129 shape.addRect(SkRect::MakeWH(SkIntToScalar(subset.width()),
2172 SkIntToScalar( subset.height()))); 2130 SkIntToScalar( subset.height())));
2173 shape.transform(matrix); 2131 shape.transform(matrix);
2174 content.setShape(shape); 2132 content.setShape(shape);
2175 } 2133 }
2176 if (!content.needSource()) { 2134 if (!content.needSource()) {
2177 return; 2135 return;
2178 } 2136 }
2179 2137
2180 SkAutoTUnref<SkPDFObject> image( 2138 SkAutoTUnref<SkPDFObject> image(
2181 SkPDFCreateImageObject(*bitmap, subset, fEncoder)); 2139 SkPDFCreateImageObject(fCanon, *bitmap, subset, fEncoder));
2182 if (!image) { 2140 if (!image) {
2183 return; 2141 return;
2184 } 2142 }
2185 2143
2186 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), 2144 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()),
2187 &content.entry()->fContent); 2145 &content.entry()->fContent);
2188 } 2146 }
2189
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698