| /* | |
| * Copyright 2015 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "SkImage.h" | |
| #include "SkPDFBitmap.h" | |
| #include "SkPDFCanon.h" | |
| #include "SkPDFFont.h" | |
| #include "SkPDFShader.h" | |
| //////////////////////////////////////////////////////////////////////////////// | |
| void SkPDFCanon::reset() { | |
| for (int i = 0; i < fFontRecords.count(); ++i) { | |
| fFontRecords[i].fFont->unref(); | |
| } | |
| fFontRecords.reset(); | |
| fFunctionShaderRecords.unrefAll(); | |
| fFunctionShaderRecords.reset(); | |
| fAlphaShaderRecords.unrefAll(); | |
| fAlphaShaderRecords.reset(); | |
| fImageShaderRecords.unrefAll(); | |
| fImageShaderRecords.reset(); | |
| fGraphicStateRecords.foreach ([](WrapGS w) { w.fPtr->unref(); }); | |
| fGraphicStateRecords.reset(); | |
| fBitmapToImageMap.foreach( | |
| [](SkBitmapKey, const SkImage** p) { SkSafeUnref(*p); }); | |
| fBitmapToImageMap.reset(); | |
| fPDFBitmapMap.foreach([](uint32_t, SkPDFObject** p) { SkSafeUnref(*p); }); | |
| fPDFBitmapMap.reset(); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| template <class T> T* assert_ptr(T* p) { SkASSERT(p); return p; } | |
| // requires `bool T::equals(const U&) const` | |
| template <typename T, typename U> | |
| T* find_item(const SkTDArray<T*>& ptrArray, const U& object) { | |
| for (int i = 0; i < ptrArray.count(); ++i) { | |
| if (ptrArray[i]->equals(object)) { | |
| return ptrArray[i]; | |
| } | |
| } | |
| return nullptr; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| SkPDFFont* SkPDFCanon::findFont(uint32_t fontID, | |
| uint16_t glyphID, | |
| SkPDFFont** relatedFontPtr) const { | |
| SkASSERT(relatedFontPtr); | |
| SkPDFFont* relatedFont = nullptr; | |
| for (int i = 0; i < fFontRecords.count(); ++i) { | |
| SkPDFFont::Match match = SkPDFFont::IsMatch( | |
| fFontRecords[i].fFont, fFontRecords[i].fFontID, | |
| fFontRecords[i].fGlyphID, fontID, glyphID); | |
| if (SkPDFFont::kExact_Match == match) { | |
| return fFontRecords[i].fFont; | |
| } else if (!relatedFont && SkPDFFont::kRelated_Match == match) { | |
| relatedFont = fFontRecords[i].fFont; | |
| } | |
| } | |
| *relatedFontPtr = relatedFont; // May still be nullptr. | |
| return nullptr; | |
| } | |
| void SkPDFCanon::addFont(SkPDFFont* font, uint32_t fontID, uint16_t fGlyphID) { | |
| SkPDFCanon::FontRec* rec = fFontRecords.push(); | |
| rec->fFont = SkRef(font); | |
| rec->fFontID = fontID; | |
| rec->fGlyphID = fGlyphID; | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| SkPDFFunctionShader* SkPDFCanon::findFunctionShader( | |
| const SkPDFShader::State& state) const { | |
| return find_item(fFunctionShaderRecords, state); | |
| } | |
| void SkPDFCanon::addFunctionShader(SkPDFFunctionShader* pdfShader) { | |
| fFunctionShaderRecords.push(SkRef(pdfShader)); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| SkPDFAlphaFunctionShader* SkPDFCanon::findAlphaShader( | |
| const SkPDFShader::State& state) const { | |
| return find_item(fAlphaShaderRecords, state); | |
| } | |
| void SkPDFCanon::addAlphaShader(SkPDFAlphaFunctionShader* pdfShader) { | |
| fAlphaShaderRecords.push(SkRef(pdfShader)); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| SkPDFImageShader* SkPDFCanon::findImageShader( | |
| const SkPDFShader::State& state) const { | |
| return find_item(fImageShaderRecords, state); | |
| } | |
| void SkPDFCanon::addImageShader(SkPDFImageShader* pdfShader) { | |
| fImageShaderRecords.push(SkRef(pdfShader)); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| const SkPDFGraphicState* SkPDFCanon::findGraphicState( | |
| const SkPDFGraphicState& key) const { | |
| const WrapGS* ptr = fGraphicStateRecords.find(WrapGS(&key)); | |
| return ptr ? ptr->fPtr : nullptr; | |
| } | |
| void SkPDFCanon::addGraphicState(const SkPDFGraphicState* state) { | |
| SkASSERT(state); | |
| WrapGS w(SkRef(state)); | |
| SkASSERT(!fGraphicStateRecords.contains(w)); | |
| fGraphicStateRecords.add(w); | |
| } | |
| //////////////////////////////////////////////////////////////////////////////// | |
| SkPDFObject* SkPDFCanon::findPDFBitmap(const SkImage* image) const { | |
| SkPDFObject** ptr = fPDFBitmapMap.find(image->uniqueID()); | |
| return ptr ? *ptr : nullptr; | |
| } | |
| void SkPDFCanon::addPDFBitmap(uint32_t imageUniqueID, SkPDFObject* pdfBitmap) { | |
| fPDFBitmapMap.set(imageUniqueID, SkRef(pdfBitmap)); | |
| } | |
| const SkImage* SkPDFCanon::bitmapToImage(const SkBitmap& bm) { | |
| // reference remains owned by the fBitmapToImageMap! | |
| SkBitmapKey key(bm); | |
| if (const SkImage** img = fBitmapToImageMap.find(key)) { | |
| return *img; | |
| } | |
| if (SkImage* image = SkImage::NewFromBitmap(bm)) { | |
| return *fBitmapToImageMap.set(key, image); | |
| } | |
| SkBitmap n32bitmap; // SkImage::NewFromBitmap can be finicky. | |
| bm.copyTo(&n32bitmap, kN32_SkColorType); | |
| return *fBitmapToImageMap.set(key, SkImage::NewFromBitmap(n32bitmap)); | |
| } |