#include "SkIStream.h"
#include "SkMaskFilter.h"
#include "SkPaint.h"
+#include "SkPathOps.h"
#include "SkPoint.h"
#include "SkRasterizer.h"
#include "SkSFNTHeader.h"
//make it clear when converting a scalar that this is what is wanted.
#define SkScalarToFLOAT(n) SkScalarToFloat(n)
-//Dummy representation of a GUID from create_id.
+//Dummy representation of a GUID from createId.
#define L_GUID_ID L"XXXXXXXXsXXXXsXXXXsXXXXsXXXXXXXXXXXX"
-//Length of GUID representation from create_id, including NULL terminator.
+//Length of GUID representation from createId, including NULL terminator.
#define GUID_ID_LEN SK_ARRAY_COUNT(L_GUID_ID)
/**
guid.Data4[7]);
}
-/**
- Creates a GUID based id and places it into buffer.
- buffer should have space for at least GUID_ID_LEN wide characters.
- The string will always be wchar null terminated.
- XXXXXXXXsXXXXsXXXXsXXXXsXXXXXXXXXXXX0
- The string may begin with a digit,
- and so may not be suitable as a bare resource key.
- */
-static HRESULT create_id(wchar_t* buffer, size_t bufferSize,
- wchar_t sep = '-') {
+HRESULT SkXPSDevice::createId(wchar_t* buffer, size_t bufferSize, wchar_t sep) {
GUID guid = {};
+#ifdef SK_XPS_USE_DETERMINISTIC_IDS
+ guid.Data1 = fNextId++;
+ // The following make this a valid Type4 UUID.
+ guid.Data3 = 0x4000;
+ guid.Data4[0] = 0x80;
+#else
HRM(CoCreateGuid(&guid), "Could not create GUID for id.");
+#endif
if (format_guid(guid, buffer, bufferSize, sep) == -1) {
HRM(E_UNEXPECTED, "Could not format GUID into id.");
swprintf_s(buffer, size, L"/Documents/1/Metadata/%u.png", pageNum);
} else {
wchar_t id[GUID_ID_LEN];
- HR(create_id(id, GUID_ID_LEN));
+ HR(this->createId(id, GUID_ID_LEN));
swprintf_s(buffer, size, L"/Metadata/%s.png", id);
}
HRM(this->fXpsFactory->CreatePartUri(buffer, &partUri),
SK_ARRAY_COUNT(L"/Documents/1/Resources/Images/" L_GUID_ID L".png");
wchar_t buffer[size];
wchar_t id[GUID_ID_LEN];
- HR(create_id(id, GUID_ID_LEN));
+ HR(this->createId(id, GUID_ID_LEN));
swprintf_s(buffer, size, L"/Documents/1/Resources/Images/%s.png", id);
SkTScopedComPtr<IOpcPartUri> imagePartUri;
SkTScopedComPtr<IXpsOMMatrixTransform> xpsMatrixToUse;
HR(this->createXpsTransform(localMatrix, &xpsMatrixToUse));
- if (NULL != xpsMatrixToUse.get()) {
+ if (xpsMatrixToUse.get()) {
HRM((*xpsBrush)->SetTransformLocal(xpsMatrixToUse.get()),
"Could not set transform for image brush.");
} else {
IXpsOMBrush** xpsBrush) {
XPS_POINT startPoint;
XPS_POINT endPoint;
- if (NULL != xpsMatrix) {
+ if (xpsMatrix) {
startPoint = xps_point(info.fPoint[0]);
endPoint = xps_point(info.fPoint[1]);
} else {
&endPoint,
&gradientBrush),
"Could not create linear gradient brush.");
- if (NULL != xpsMatrix) {
+ if (xpsMatrix) {
HRM(gradientBrush->SetTransformLocal(xpsMatrix),
"Could not set transform on linear gradient brush.");
}
XPS_POINT centerPoint;
XPS_POINT gradientOrigin;
XPS_SIZE radiiSizes;
- if (NULL != xpsMatrix) {
+ if (xpsMatrix) {
centerPoint = xps_point(info.fPoint[0]);
gradientOrigin = xps_point(info.fPoint[0]);
radiiSizes.width = SkScalarToFLOAT(info.fRadius[0]);
&radiiSizes,
&gradientBrush),
"Could not create radial gradient brush.");
- if (NULL != xpsMatrix) {
+ if (xpsMatrix) {
HRM(gradientBrush->SetTransformLocal(xpsMatrix),
"Could not set transform on radial gradient brush.");
}
}
SkMatrix localMatrix = shader->getLocalMatrix();
- if (NULL != parentTransform) {
+ if (parentTransform) {
localMatrix.preConcat(*parentTransform);
}
SkTScopedComPtr<IXpsOMMatrixTransform> xpsMatrixToUse;
case SkShader::kDefault_BitmapType: {
//TODO: outMatrix??
SkMatrix localMatrix = shader->getLocalMatrix();
- if (NULL != parentTransform) {
+ if (parentTransform) {
localMatrix.preConcat(*parentTransform);
}
while ((verb = iter.next(points)) != SkPath::kDone_Verb) {
switch (verb) {
case SkPath::kMove_Verb: {
- if (NULL != xpsFigure.get()) {
+ if (xpsFigure.get()) {
HR(close_figure(segmentTypes, segmentStrokes, segmentData,
stroke, fill,
xpsFigure.get() , xpsFigures));
break;
}
}
- if (NULL != xpsFigure.get()) {
+ if (xpsFigure.get()) {
HR(close_figure(segmentTypes, segmentStrokes, segmentData,
stroke, fill,
xpsFigure.get(), xpsFigures));
return S_OK;
}
-HRESULT SkXPSDevice::drawInverseWindingPath(const SkDraw& d,
- const SkPath& devicePath,
- IXpsOMPath* shadedPath) {
- const SkRect universeRect = SkRect::MakeLTRB(0, 0,
- this->fCurrentCanvasSize.fWidth, this->fCurrentCanvasSize.fHeight);
-
- const XPS_RECT universeRectXps = {
- 0.0f, 0.0f,
- SkScalarToFLOAT(this->fCurrentCanvasSize.fWidth),
- SkScalarToFLOAT(this->fCurrentCanvasSize.fHeight),
- };
-
- //Get the geometry.
- SkTScopedComPtr<IXpsOMGeometry> shadedGeometry;
- HRM(shadedPath->GetGeometry(&shadedGeometry),
- "Could not get shaded geometry for inverse path.");
-
- //Get the figures from the geometry.
- SkTScopedComPtr<IXpsOMGeometryFigureCollection> shadedFigures;
- HRM(shadedGeometry->GetFigures(&shadedFigures),
- "Could not get shaded figures for inverse path.");
-
- HRM(shadedGeometry->SetFillRule(XPS_FILL_RULE_NONZERO),
- "Could not set shaded fill rule for inverse path.");
-
- //Take everything drawn so far, and make a shared resource out of it.
- //Replace everything drawn so far with
- //inverse canvas
- // old canvas of everything so far
- // world shaded figure, clipped to current clip
- // top canvas of everything so far, clipped to path
- //Note: this is not quite right when there is nothing solid in the
- //canvas of everything so far, as the bit on top will allow
- //the world paint to show through.
-
- //Create new canvas.
- SkTScopedComPtr<IXpsOMCanvas> newCanvas;
- HRM(this->fXpsFactory->CreateCanvas(&newCanvas),
- "Could not create inverse canvas.");
-
- //Save the old canvas to a dictionary on the new canvas.
- SkTScopedComPtr<IXpsOMDictionary> newDictionary;
- HRM(this->fXpsFactory->CreateDictionary(&newDictionary),
- "Could not create inverse dictionary.");
- HRM(newCanvas->SetDictionaryLocal(newDictionary.get()),
- "Could not set inverse dictionary.");
-
- const size_t size = SK_ARRAY_COUNT(L"ID" L_GUID_ID);
- wchar_t buffer[size];
- wchar_t id[GUID_ID_LEN];
- HR(create_id(id, GUID_ID_LEN, '_'));
- swprintf_s(buffer, size, L"ID%s", id);
- HRM(newDictionary->Append(buffer, this->fCurrentXpsCanvas.get()),
- "Could not add canvas to inverse dictionary.");
-
- //Start drawing
- SkTScopedComPtr<IXpsOMVisualCollection> newVisuals;
- HRM(newCanvas->GetVisuals(&newVisuals),
- "Could not get inverse canvas visuals.");
-
- //Draw old canvas from dictionary onto new canvas.
- SkTScopedComPtr<IXpsOMGeometry> oldGeometry;
- HRM(this->fXpsFactory->CreateGeometry(&oldGeometry),
- "Could not create old inverse geometry.");
-
- SkTScopedComPtr<IXpsOMGeometryFigureCollection> oldFigures;
- HRM(oldGeometry->GetFigures(&oldFigures),
- "Could not get old inverse figures.");
-
- SkTScopedComPtr<IXpsOMGeometryFigure> oldFigure;
- HR(this->createXpsRect(universeRect, FALSE, TRUE, &oldFigure));
- HRM(oldFigures->Append(oldFigure.get()),
- "Could not add old inverse figure.");
-
- SkTScopedComPtr<IXpsOMVisualBrush> oldBrush;
- HRM(this->fXpsFactory->CreateVisualBrush(&universeRectXps,
- &universeRectXps,
- &oldBrush),
- "Could not create old inverse brush.");
-
- SkTScopedComPtr<IXpsOMPath> oldPath;
- HRM(this->fXpsFactory->CreatePath(&oldPath),
- "Could not create old inverse path.");
- HRM(oldPath->SetGeometryLocal(oldGeometry.get()),
- "Could not set old inverse geometry.");
- HRM(oldPath->SetFillBrushLocal(oldBrush.get()),
- "Could not set old inverse fill brush.");
- //the brush must be parented before setting the lookup.
- HRM(newVisuals->Append(oldPath.get()),
- "Could not add old inverse path to new canvas visuals.");
- HRM(oldBrush->SetVisualLookup(buffer),
- "Could not set old inverse brush visual lookup.");
-
- //Draw the clip filling shader.
- SkTScopedComPtr<IXpsOMGeometryFigure> shadedFigure;
- HR(this->createXpsRect(universeRect, FALSE, TRUE, &shadedFigure));
- HRM(shadedFigures->Append(shadedFigure.get()),
- "Could not add inverse shaded figure.");
- //the geometry is already set
- HR(this->clip(shadedPath, d));
- HRM(newVisuals->Append(shadedPath),
- "Could not add inverse shaded path to canvas visuals.");
-
- //Draw the old canvas on top, clipped to the original path.
- SkTScopedComPtr<IXpsOMCanvas> topCanvas;
- HRM(this->fXpsFactory->CreateCanvas(&topCanvas),
- "Could not create top inverse canvas.");
- //Clip the canvas to prevent alpha spill.
- //This is the entire reason this canvas exists.
- HR(this->clip(topCanvas.get(), d));
-
- SkTScopedComPtr<IXpsOMGeometry> topGeometry;
- HRM(this->fXpsFactory->CreateGeometry(&topGeometry),
- "Could not create top inverse geometry.");
-
- SkTScopedComPtr<IXpsOMGeometryFigureCollection> topFigures;
- HRM(topGeometry->GetFigures(&topFigures),
- "Could not get top inverse figures.");
-
- SkTScopedComPtr<IXpsOMGeometryFigure> topFigure;
- HR(this->createXpsRect(universeRect, FALSE, TRUE, &topFigure));
- HRM(topFigures->Append(topFigure.get()),
- "Could not add old inverse figure.");
-
- SkTScopedComPtr<IXpsOMVisualBrush> topBrush;
- HRM(this->fXpsFactory->CreateVisualBrush(&universeRectXps,
- &universeRectXps,
- &topBrush),
- "Could not create top inverse brush.");
-
- SkTScopedComPtr<IXpsOMPath> topPath;
- HRM(this->fXpsFactory->CreatePath(&topPath),
- "Could not create top inverse path.");
- HRM(topPath->SetGeometryLocal(topGeometry.get()),
- "Could not set top inverse geometry.");
- HRM(topPath->SetFillBrushLocal(topBrush.get()),
- "Could not set top inverse fill brush.");
- //the brush must be parented before setting the lookup.
- HRM(newVisuals->Append(topCanvas.get()),
- "Could not add top canvas to inverse canvas visuals.");
- SkTScopedComPtr<IXpsOMVisualCollection> topVisuals;
- HRM(topCanvas->GetVisuals(&topVisuals),
- "Could not get top inverse canvas visuals.");
- HRM(topVisuals->Append(topPath.get()),
- "Could not add top inverse path to top canvas visuals.");
- HRM(topBrush->SetVisualLookup(buffer),
- "Could not set top inverse brush visual lookup.");
-
- HR(this->clipToPath(topPath.get(), devicePath, XPS_FILL_RULE_NONZERO));
-
- //swap current canvas to new canvas
- this->fCurrentXpsCanvas.swap(newCanvas);
-
- return S_OK;
-}
-
void SkXPSDevice::convertToPpm(const SkMaskFilter* filter,
SkMatrix* matrix,
SkVector* ppuScale,
bool xpsTransformsPath = true;
//Set the fill rule.
+ SkPath* xpsCompatiblePath = fillablePath;
XPS_FILL_RULE xpsFillRule;
- switch (platonicPath.getFillType()) {
+ switch (fillablePath->getFillType()) {
case SkPath::kWinding_FillType:
xpsFillRule = XPS_FILL_RULE_NONZERO;
break;
xpsFillRule = XPS_FILL_RULE_EVENODD;
break;
case SkPath::kInverseWinding_FillType: {
- //[Fillable-path -> Device-path]
- SkPath* devicePath = pathIsMutable ? fillablePath : &modifiedPath;
- fillablePath->transform(matrix, devicePath);
-
- HRV(this->drawInverseWindingPath(d,
- *devicePath,
- shadedPath.get()));
- return;
+ //[Fillable-path (inverse winding) -> XPS-path (inverse even odd)]
+ if (!pathIsMutable) {
+ xpsCompatiblePath = &modifiedPath;
+ pathIsMutable = true;
+ }
+ if (!Simplify(*fillablePath, xpsCompatiblePath)) {
+ SkDEBUGF(("Could not simplify inverse winding path."));
+ return;
+ }
}
+ // The xpsCompatiblePath is noW inverse even odd, so fall through.
case SkPath::kInverseEvenOdd_FillType: {
const SkRect universe = SkRect::MakeLTRB(
0, 0,
}
}
- SkPath* devicePath = fillablePath;
+ SkPath* devicePath = xpsCompatiblePath;
if (!xpsTransformsPath) {
//[Fillable-path -> Device-path]
- devicePath = pathIsMutable ? fillablePath : &modifiedPath;
- fillablePath->transform(matrix, devicePath);
+ devicePath = pathIsMutable ? xpsCompatiblePath : &modifiedPath;
+ xpsCompatiblePath->transform(matrix, devicePath);
}
HRV(this->addXpsPathGeometry(shadedFigures.get(),
stroke, fill, *devicePath));
}
SkTScopedComPtr<IXpsOMGeometryFigure> rectFigure;
- if (NULL != xpsTransform.get()) {
+ if (xpsTransform.get()) {
const SkShader::TileMode xy[2] = {
SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode,
SK_ARRAY_COUNT(L"/Resources/Fonts/" L_GUID_ID L".odttf");
wchar_t buffer[size];
wchar_t id[GUID_ID_LEN];
- HR(create_id(id, GUID_ID_LEN));
+ HR(this->createId(id, GUID_ID_LEN));
swprintf_s(buffer, size, L"/Resources/Fonts/%s.odttf", id);
SkTScopedComPtr<IOpcPartUri> partUri;
SkTScopedComPtr<IXpsOMGlyphsEditor> glyphsEditor;
HRM(glyphs->GetGlyphsEditor(&glyphsEditor), "Could not get glyph editor.");
- if (NULL != text) {
+ if (text) {
HRM(glyphsEditor->SetUnicodeString(text),
"Could not set unicode string.");
}
- if (NULL != xpsGlyphs) {
+ if (xpsGlyphs) {
HRM(glyphsEditor->SetGlyphIndices(xpsGlyphsLen, xpsGlyphs),
"Could not set glyphs.");
}