OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 | |
OLD | NEW |