staticvoid fill_color_from_bitmap(SkCanvas* canvas, float left, float top, float right, float bottom, const SkBitmap& bitmap, int x, int y, float alpha) {
SkRect rect{left, top, right, bottom}; if (!rect.isEmpty()) {
SkColor4f color = SkColor4f::FromColor(bitmap.getColor(x, y));
SkPaint paint(SkColor4f{color.fR, color.fG, color.fB, alpha * color.fA});
canvas->drawRect(rect, paint);
}
}
static SkMatrix scale_translate(SkScalar sx, SkScalar sy, SkScalar tx, SkScalar ty) {
SkMatrix m;
m.setScaleTranslate(sx, sy, tx, ty); return m;
}
staticbool is_tiled(SkTileMode m) { return SkTileMode::kMirror == m || SkTileMode::kRepeat == m; }
static SkPDFIndirectReference make_image_shader(SkPDFDocument* doc,
SkMatrix finalMatrix,
SkTileMode tileModesX,
SkTileMode tileModesY,
SkRect bBox, const SkImage* image,
SkColor4f paintColor) { // The image shader pattern cell will be drawn into a separate device // in pattern cell space (no scaling on the bitmap, though there may be // translations so that all content is in the device, coordinates > 0).
// Map clip bounds to shader space to ensure the device is large enough // to handle fake clamping.
// For tiling modes, the bounds should be extended to include the bitmap, // otherwise the bitmap gets clipped out and the shader is empty and awful. // For clamp modes, we're only interested in the clip region, whether // or not the main bitmap is in it. if (is_tiled(tileModesX) || is_tiled(tileModesY)) {
deviceBounds.join(bitmapBounds);
}
// Translate the canvas so that the bitmap origin is at (0, 0).
canvas.translate(-deviceBounds.left(), -deviceBounds.top());
patternBBox.offset(-deviceBounds.left(), -deviceBounds.top()); // Undo the translation in the final matrix
finalMatrix.preTranslate(deviceBounds.left(), deviceBounds.top());
// If the bitmap is out of bounds (i.e. clamp mode where we only see the // stretched sides), canvas will clip this out and the extraneous data // won't be saved to the PDF.
draw(&canvas, image, paintColor);
// Then handle Clamping, which requires expanding the pattern canvas to // cover the entire surfaceBBox.
SkBitmap bitmap; if (tileModesX == SkTileMode::kClamp || tileModesY == SkTileMode::kClamp) { // For now, the easiest way to access the colors in the corners and sides is // to just make a bitmap from the image.
bitmap = to_bitmap(image);
}
// If both x and y are in clamp mode, we start by filling in the corners. // (Which are just a rectangles of the corner colors.) if (tileModesX == SkTileMode::kClamp && tileModesY == SkTileMode::kClamp) {
SkASSERT(!bitmap.drawsNothing());
// Generic fallback for unsupported shaders: // * allocate a surfaceBBox-sized bitmap // * shade the whole area // * use the result as a bitmap shader static SkPDFIndirectReference make_fallback_shader(SkPDFDocument* doc,
SkShader* shader, const SkMatrix& canvasTransform, const SkIRect& surfaceBBox,
SkColor4f paintColor) { // surfaceBBox is in device space. While that's exactly what we // want for sizing our bitmap, we need to map it into // shader space for adjustments (to match // MakeImageShader's behavior).
SkRect shaderRect = SkRect::Make(surfaceBBox); if (!SkPDFUtils::InverseTransformBBox(canvasTransform, &shaderRect)) { return SkPDFIndirectReference();
} // Clamp the bitmap size to about 1M pixels staticconstint kMaxBitmapArea = 1024 * 1024;
SkScalar bitmapArea = (float)surfaceBBox.width() * (float)surfaceBBox.height();
SkScalar rasterScale = 1.0f; if (bitmapArea > (float)kMaxBitmapArea) {
rasterScale *= SkScalarSqrt((float)kMaxBitmapArea / bitmapArea);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.