| 1239 | } // namespace |
| 1240 | |
| 1241 | void PDFExportContext::drawPathWithFilter(const MCState& state, const Path& originPath, |
| 1242 | const Matrix& matrix, const Fill& originPaint) { |
| 1243 | DEBUG_ASSERT(originPaint.maskFilter); |
| 1244 | |
| 1245 | Path path(originPath); |
| 1246 | path.transform(matrix); |
| 1247 | auto maskBound = path.getBounds(); |
| 1248 | |
| 1249 | Fill paint(originPaint); |
| 1250 | |
| 1251 | if (Types::Get(originPaint.maskFilter.get()) != Types::MaskFilterType::Shader) { |
| 1252 | return; |
| 1253 | } |
| 1254 | const auto shaderMaskFilter = static_cast<const ShaderMaskFilter*>(originPaint.maskFilter.get()); |
| 1255 | auto [picture, pictureMatrix] = MaskFilterToPicture(shaderMaskFilter); |
| 1256 | |
| 1257 | auto maskContext = makeCongruentDevice(); |
| 1258 | if (!picture) { //mask as image |
| 1259 | auto surface = Surface::Make(document->context(), static_cast<int>(maskBound.width()), |
| 1260 | static_cast<int>(maskBound.height())); |
| 1261 | Canvas* maskCanvas = surface->getCanvas(); |
| 1262 | Paint maskPaint; |
| 1263 | maskPaint.setShader(shaderMaskFilter->getShader()); |
| 1264 | maskCanvas->drawPaint(maskPaint); |
| 1265 | |
| 1266 | auto grayscaleInfo = ImageInfo::Make(surface->width(), surface->height(), ColorType::ALPHA_8); |
| 1267 | auto byteSize = grayscaleInfo.byteSize(); |
| 1268 | void* pixels = malloc(byteSize); |
| 1269 | if (!surface->readPixels(grayscaleInfo, pixels)) { |
| 1270 | free(pixels); |
| 1271 | return; |
| 1272 | } |
| 1273 | auto pixelData = Data::MakeAdopted(pixels, byteSize, Data::FreeProc); |
| 1274 | // Convert alpha-8 to a grayscale image |
| 1275 | grayscaleInfo = ImageInfo::Make(surface->width(), surface->height(), ColorType::Gray_8); |
| 1276 | auto maskImage = Image::MakeFrom(grayscaleInfo, pixelData); |
| 1277 | |
| 1278 | // PDF doesn't seem to allow masking vector graphics with an Image XObject. |
| 1279 | // Must mask with a Form XObject. |
| 1280 | { |
| 1281 | Canvas canvas(maskContext.get()); |
| 1282 | canvas.drawImage(maskImage, maskBound.x(), maskBound.y()); |
| 1283 | } |
| 1284 | } else { |
| 1285 | Canvas canvas(maskContext.get()); |
| 1286 | canvas.concat(pictureMatrix); |
| 1287 | canvas.drawPicture(picture); |
| 1288 | } |
| 1289 | |
| 1290 | if (!state.matrix.isIdentity() && paint.shader) { |
| 1291 | paint.shader = paint.shader->makeWithMatrix(matrix); |
| 1292 | } |
| 1293 | ScopedContentEntry contentEntry(this, state, Matrix::I(), paint); |
| 1294 | if (!contentEntry) { |
| 1295 | return; |
| 1296 | } |
| 1297 | |
| 1298 | setGraphicState( |
no test coverage detected