| 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 |