constchar* SkPDFUtils::BlendModeName(SkBlendMode mode) { // PDF32000.book section 11.3.5 "Blend Mode" switch (mode) { case SkBlendMode::kSrcOver: return"Normal"; case SkBlendMode::kXor: return"Normal"; // (unsupported mode) case SkBlendMode::kPlus: return"Normal"; // (unsupported mode) case SkBlendMode::kScreen: return"Screen"; case SkBlendMode::kOverlay: return"Overlay"; case SkBlendMode::kDarken: return"Darken"; case SkBlendMode::kLighten: return"Lighten"; case SkBlendMode::kColorDodge: return"ColorDodge"; case SkBlendMode::kColorBurn: return"ColorBurn"; case SkBlendMode::kHardLight: return"HardLight"; case SkBlendMode::kSoftLight: return"SoftLight"; case SkBlendMode::kDifference: return"Difference"; case SkBlendMode::kExclusion: return"Exclusion"; case SkBlendMode::kMultiply: return"Multiply"; case SkBlendMode::kHue: return"Hue"; case SkBlendMode::kSaturation: return"Saturation"; case SkBlendMode::kColor: return"Color"; case SkBlendMode::kLuminosity: return"Luminosity"; // Other blendmodes are handled in SkPDFDevice::setUpContentEntry. default: return nullptr;
}
}
void SkPDFUtils::AppendRectangle(const SkRect& rect, SkWStream* content) { // Skia has 0,0 at top left, pdf at bottom left. Do the right thing.
SkScalar bottom = std::min(rect.fBottom, rect.fTop);
void SkPDFUtils::EmitPath(const SkPath& path, SkPaint::Style paintStyle, bool doConsumeDegerates, SkWStream* content,
SkScalar tolerance) { if (path.isEmpty() && SkPaint::kFill_Style == paintStyle) {
SkPDFUtils::AppendRectangle({0, 0, 0, 0}, content); return;
} // Filling a path with no area results in a drawing in PDF renderers but // Chrome expects to be able to draw some such entities with no visible // result, so we detect those cases and discard the drawing for them. // Specifically: moveTo(X), lineTo(Y) and moveTo(X), lineTo(X), lineTo(Y).
SkRect rect; bool isClosed; // Both closure and direction need to be checked.
SkPathDirection direction; if (path.isRect(&rect, &isClosed, &direction) &&
isClosed &&
(SkPathDirection::kCW == direction ||
SkPathFillType::kEvenOdd == path.getFillType()))
{
SkPDFUtils::AppendRectangle(rect, content); return;
}
enum SkipFillState {
kEmpty_SkipFillState,
kSingleLine_SkipFillState,
kNonSingleLine_SkipFillState,
};
SkipFillState fillState = kEmpty_SkipFillState; //if (paintStyle != SkPaint::kFill_Style) { // fillState = kNonSingleLine_SkipFillState; //}
SkPoint lastMovePt = SkPoint::Make(0,0);
SkDynamicMemoryWStream currentSegment;
SkPoint args[4];
SkPath::Iter iter(path, false); for (SkPath::Verb verb = iter.next(args);
verb != SkPath::kDone_Verb;
verb = iter.next(args)) { // args gets all the points, even the implicit first point. switch (verb) { case SkPath::kMove_Verb:
MoveTo(args[0].fX, args[0].fY, ¤tSegment);
lastMovePt = args[0];
fillState = kEmpty_SkipFillState; break; case SkPath::kLine_Verb: if (!doConsumeDegerates || !SkPathPriv::AllPointsEq(args, 2)) {
AppendLine(args[1].fX, args[1].fY, ¤tSegment); if ((fillState == kEmpty_SkipFillState) && (args[0] != lastMovePt)) {
fillState = kSingleLine_SkipFillState; break;
}
fillState = kNonSingleLine_SkipFillState;
} break; case SkPath::kQuad_Verb: if (!doConsumeDegerates || !SkPathPriv::AllPointsEq(args, 3)) {
append_quad(args, ¤tSegment);
fillState = kNonSingleLine_SkipFillState;
} break; case SkPath::kConic_Verb: if (!doConsumeDegerates || !SkPathPriv::AllPointsEq(args, 3)) {
SkAutoConicToQuads converter; const SkPoint* quads = converter.computeQuads(args, iter.conicWeight(), tolerance); for (int i = 0; i < converter.countQuads(); ++i) {
append_quad(&quads[i * 2], ¤tSegment);
}
fillState = kNonSingleLine_SkipFillState;
} break; case SkPath::kCubic_Verb: if (!doConsumeDegerates || !SkPathPriv::AllPointsEq(args, 4)) {
append_cubic(args[1].fX, args[1].fY, args[2].fX, args[2].fY,
args[3].fX, args[3].fY, ¤tSegment);
fillState = kNonSingleLine_SkipFillState;
} break; case SkPath::kClose_Verb:
ClosePath(¤tSegment);
currentSegment.writeToStream(content);
currentSegment.reset(); break; default:
SkASSERT(false); break;
}
} if (currentSegment.bytesWritten() > 0) {
currentSegment.writeToStream(content);
}
}
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.