9#if defined(SK_BUILD_FOR_WIN)
20#include <XpsObjectModel.h>
66#define SkScalarToFLOAT(n) SkScalarToFloat(n)
69#define L_GUID_ID L"XXXXXXXXsXXXXsXXXXsXXXXsXXXXXXXXXXXX"
71#define GUID_ID_LEN std::size(L_GUID_ID)
80static int format_guid(
const GUID& guid,
81 wchar_t*
buffer,
size_t bufferSize,
86 L"%08lX%c%04X%c%04X%c%02X%02X%c%02X%02X%02X%02X%02X%02X",
104HRESULT SkXPSDevice::createId(
wchar_t*
buffer,
size_t bufferSize,
wchar_t sep) {
106#ifdef SK_XPS_USE_DETERMINISTIC_IDS
107 guid.Data1 = fNextId++;
110 guid.Data4[0] = 0x80;
112 HRM(CoCreateGuid(&guid),
"Could not create GUID for id.");
115 if (format_guid(guid,
buffer, bufferSize,
sep) == -1) {
116 HRM(E_UNEXPECTED,
"Could not format GUID into id.");
125 , fTopTypefaces(&fTypefaces) {}
127SkXPSDevice::~SkXPSDevice() {}
129bool SkXPSDevice::beginPortfolio(
SkWStream* outputStream, IXpsOMObjectFactory* factory) {
131 fXpsFactory.reset(SkRefComPtr(factory));
132 HRB(SkWIStream::CreateFromSkWStream(outputStream, &this->fOutputStream));
136bool SkXPSDevice::beginSheet(
144 ++this->fCurrentPage;
148 this->fCurrentCanvasSize = trimSize;
149 this->fCurrentUnitsPerMeter = unitsPerMeter;
150 this->fCurrentPixelsPerMeter = pixelsPerMeter;
151 return this->createCanvasForLayer();
154bool SkXPSDevice::createCanvasForLayer() {
156 fCurrentXpsCanvas.reset();
157 HRB(fXpsFactory->CreateCanvas(&fCurrentXpsCanvas));
161template <
typename T>
static constexpr size_t sk_digits_in() {
162 return static_cast<size_t>(std::numeric_limits<T>::digits10 + 1);
165HRESULT SkXPSDevice::createXpsThumbnail(IXpsOMPage*
page,
166 const unsigned int pageNum,
167 IXpsOMImageResource**
image) {
168 SkTScopedComPtr<IXpsOMThumbnailGenerator> thumbnailGenerator;
169 HRM(CoCreateInstance(
170 CLSID_XpsOMThumbnailGenerator,
172 CLSCTX_INPROC_SERVER,
173 IID_PPV_ARGS(&thumbnailGenerator)),
174 "Could not create thumbnail generator.");
176 SkTScopedComPtr<IOpcPartUri> partUri;
178 std::size(
L"/Documents/1/Metadata/.png") + sk_digits_in<
decltype(pageNum)>(),
182 swprintf_s(
buffer,
size,
L"/Documents/1/Metadata/%u.png", pageNum);
184 wchar_t id[GUID_ID_LEN];
185 HR(this->createId(
id, GUID_ID_LEN));
188 HRM(this->fXpsFactory->CreatePartUri(
buffer, &partUri),
189 "Could not create thumbnail part uri.");
191 HRM(thumbnailGenerator->GenerateThumbnail(
page,
193 XPS_THUMBNAIL_SIZE_LARGE,
196 "Could not generate thumbnail.");
201HRESULT SkXPSDevice::createXpsPage(
const XPS_SIZE& pageSize,
203 constexpr size_t size =
205 + sk_digits_in<decltype(fCurrentPage)>();
207 swprintf_s(
buffer,
size,
L"/Documents/1/Pages/%u.fpage",
209 SkTScopedComPtr<IOpcPartUri> partUri;
210 HRM(this->fXpsFactory->CreatePartUri(
buffer, &partUri),
211 "Could not create page part uri.");
214 HRM(this->fXpsFactory->CreatePage(&pageSize,
218 "Could not create page.");
223HRESULT SkXPSDevice::initXpsDocumentWriter(IXpsOMImageResource*
image) {
226 SkTScopedComPtr<IOpcPartUri> partUri;
227 HRM(this->fXpsFactory->CreatePartUri(
L"/FixedDocumentSequence.fdseq",
229 "Could not create document sequence part uri.");
230 HRM(this->fXpsFactory->CreatePackageWriterOnStream(
231 this->fOutputStream.get(),
233 XPS_INTERLEAVING_OFF,
239 &this->fPackageWriter),
240 "Could not create package writer.");
245 SkTScopedComPtr<IOpcPartUri> partUri;
246 HRM(this->fXpsFactory->CreatePartUri(
247 L"/Documents/1/FixedDocument.fdoc",
249 "Could not create fixed document part uri.");
250 HRM(this->fPackageWriter->StartNewDocument(partUri.get(),
255 "Could not start document.");
261bool SkXPSDevice::endSheet() {
263 static const float xpsDPI = 96.0f;
264 static const float inchesPerMeter = 10000.0f / 254.0f;
265 static const float targetUnitsPerMeter = xpsDPI * inchesPerMeter;
266 const float scaleX = targetUnitsPerMeter
267 / SkScalarToFLOAT(this->fCurrentUnitsPerMeter.fX);
268 const float scaleY = targetUnitsPerMeter
269 / SkScalarToFLOAT(this->fCurrentUnitsPerMeter.fY);
272 SkTScopedComPtr<IXpsOMCanvas> scaleCanvas;
273 HRBM(this->fXpsFactory->CreateCanvas(&scaleCanvas),
274 "Could not create scale canvas.");
275 SkTScopedComPtr<IXpsOMVisualCollection> scaleCanvasVisuals;
276 HRBM(scaleCanvas->GetVisuals(&scaleCanvasVisuals),
277 "Could not get scale canvas visuals.");
279 SkTScopedComPtr<IXpsOMMatrixTransform> geomToPhys;
280 XPS_MATRIX rawGeomToPhys = { scaleX, 0, 0, scaleY, 0, 0, };
281 HRBM(this->fXpsFactory->CreateMatrixTransform(&rawGeomToPhys, &geomToPhys),
282 "Could not create geometry to physical transform.");
283 HRBM(scaleCanvas->SetTransformLocal(geomToPhys.get()),
284 "Could not set transform on scale canvas.");
287 HRBM(scaleCanvasVisuals->Append(this->fCurrentXpsCanvas.get()),
288 "Could not add base canvas to scale canvas.");
291 XPS_SIZE pageSize = {
292 SkScalarToFLOAT(this->fCurrentCanvasSize.width()) * scaleX,
293 SkScalarToFLOAT(this->fCurrentCanvasSize.height()) * scaleY,
295 SkTScopedComPtr<IXpsOMPage>
page;
296 HRB(this->createXpsPage(pageSize, &
page));
298 SkTScopedComPtr<IXpsOMVisualCollection> pageVisuals;
299 HRBM(
page->GetVisuals(&pageVisuals),
"Could not get page visuals.");
302 HRBM(pageVisuals->Append(scaleCanvas.get()),
303 "Could not add scale canvas to page.");
306 if (
nullptr == this->fPackageWriter.get()) {
307 SkTScopedComPtr<IXpsOMImageResource>
image;
309 this->createXpsThumbnail(
page.get(), 0, &
image);
311 HRB(this->initXpsDocumentWriter(
image.
get()));
314 HRBM(this->fPackageWriter->AddPage(
page.get(),
320 "Could not write the page.");
321 this->fCurrentXpsCanvas.reset();
326static HRESULT subset_typeface(
const SkXPSDevice::TypefaceUse& current) {
328 #if defined(SK_WINUWP)
333 std::vector<unsigned short> keepList;
334 current.glyphsUsed.forEachSetIndex([&keepList](
size_t v) {
335 keepList.push_back((
unsigned short)v);
338 int ttcCount = (current.ttcIndex + 1);
341 unsigned char *fontPackageBufferRaw =
nullptr;
342 unsigned long fontPackageBufferSize;
343 unsigned long bytesWritten;
344 unsigned long result = CreateFontPackage(
345 (
const unsigned char *) current.fontData->getMemoryBase(),
346 (
unsigned long) current.fontData->getLength(),
347 &fontPackageBufferRaw,
348 &fontPackageBufferSize,
350 TTFCFP_FLAGS_SUBSET | TTFCFP_FLAGS_GLYPHLIST | (ttcCount > 0 ? TTFCFP_FLAGS_TTC : 0),
357 SkTo<unsigned short>(keepList.size()),
374 fontPackageBuffer.realloc(bytesWritten + extra);
376 memmove(fontPackageBuffer.get() + extra, fontPackageBuffer.get(), bytesWritten);
383 SK_OT_ULONG* offsetPtr = SkTAfter<SK_OT_ULONG>(ttcfHeader);
384 for (
int i = 0;
i < ttcCount; ++
i, ++offsetPtr) {
389 SkSFNTHeader* sfntHeader = SkTAddOffset<SkSFNTHeader>(fontPackageBuffer.get(), extra);
392 SkTAfter<SkSFNTHeader::TableDirectoryEntry>(sfntHeader);
393 for (
int i = 0;
i < numTables; ++
i, ++tableDirectory) {
399 fontPackageBuffer.realloc(bytesWritten);
403 newStream->setMemoryOwned(fontPackageBuffer.release(), bytesWritten + extra);
405 SkTScopedComPtr<IStream> newIStream;
406 SkIStream::CreateFromSkStream(std::move(newStream), &newIStream);
408 XPS_FONT_EMBEDDING embedding;
409 HRM(current.xpsFont->GetEmbeddingOption(&embedding),
410 "Could not get embedding option from font.");
412 SkTScopedComPtr<IOpcPartUri> partUri;
413 HRM(current.xpsFont->GetPartName(&partUri),
414 "Could not get part uri from font.");
416 HRM(current.xpsFont->SetContent(
420 "Could not set new stream for subsetted font.");
426bool SkXPSDevice::endPortfolio() {
428 for (
const TypefaceUse& current : *this->fTopTypefaces) {
430 subset_typeface(current);
433 if (this->fPackageWriter) {
434 HRBM(this->fPackageWriter->Close(),
"Could not close writer.");
440static XPS_COLOR xps_color(
const SkColor skColor) {
443 xpsColor.colorType = XPS_COLOR_TYPE_SRGB;
452static XPS_POINT xps_point(
const SkPoint& point) {
453 XPS_POINT xpsPoint = {
454 SkScalarToFLOAT(point.
fX),
455 SkScalarToFLOAT(point.
fY),
462 matrix.mapXY(point.
fX, point.
fY, &skTransformedPoint);
463 return xps_point(skTransformedPoint);
466static XPS_SPREAD_METHOD xps_spread_method(
SkTileMode tileMode) {
469 return XPS_SPREAD_METHOD_PAD;
471 return XPS_SPREAD_METHOD_REPEAT;
473 return XPS_SPREAD_METHOD_REFLECT;
476 return XPS_SPREAD_METHOD_PAD;
480 return XPS_SPREAD_METHOD_PAD;
483static void transform_offsets(
SkScalar* stopOffsets,
const int numOffsets,
492 SkScalar startToEnd = (endTransformed.
fX - startTransformed.
fX)
493 + (endTransformed.
fY - startTransformed.
fY);
495 for (
int i = 0;
i < numOffsets; ++
i) {
501 for (
int i = 0;
i < numOffsets; ++
i) {
510 SkScalar startToStop = (stopTransformed.
fX - startTransformed.
fX)
511 + (stopTransformed.
fY - startTransformed.
fY);
513 stopOffsets[
i] = startToStop / startToEnd;
518 IXpsOMMatrixTransform** xpsTransform) {
520 if (!
matrix.asAffine(affine)) {
521 *xpsTransform =
nullptr;
524 XPS_MATRIX rawXpsMatrix = {
532 HRM(this->fXpsFactory->CreateMatrixTransform(&rawXpsMatrix, xpsTransform),
533 "Could not create transform.");
538HRESULT SkXPSDevice::createPath(IXpsOMGeometryFigure* figure,
539 IXpsOMVisualCollection* visuals,
541 SkTScopedComPtr<IXpsOMGeometry> geometry;
542 HRM(this->fXpsFactory->CreateGeometry(&geometry),
543 "Could not create geometry.");
545 SkTScopedComPtr<IXpsOMGeometryFigureCollection> figureCollection;
546 HRM(geometry->GetFigures(&figureCollection),
"Could not get figures.");
547 HRM(figureCollection->Append(figure),
"Could not add figure.");
549 HRM(this->fXpsFactory->CreatePath(
path),
"Could not create path.");
550 HRM((*path)->SetGeometryLocal(geometry.get()),
"Could not set geometry");
552 HRM(visuals->Append(*
path),
"Could not add path to visuals.");
556HRESULT SkXPSDevice::createXpsSolidColorBrush(
const SkColor skColor,
558 IXpsOMBrush** xpsBrush) {
559 XPS_COLOR xpsColor = xps_color(skColor);
560 SkTScopedComPtr<IXpsOMSolidColorBrush> solidBrush;
561 HRM(this->fXpsFactory->CreateSolidColorBrush(&xpsColor,
nullptr, &solidBrush),
562 "Could not create solid color brush.");
563 HRM(solidBrush->SetOpacity(alpha / 255.0f),
"Could not set opacity.");
564 HRM(solidBrush->QueryInterface<IXpsOMBrush>(xpsBrush),
"QI Fail.");
568HRESULT SkXPSDevice::sideOfClamp(
const SkRect& areaToFill,
569 const XPS_RECT& imageViewBox,
570 IXpsOMImageResource*
image,
571 IXpsOMVisualCollection* visuals) {
572 SkTScopedComPtr<IXpsOMGeometryFigure> areaToFillFigure;
573 HR(this->createXpsRect(areaToFill,
FALSE,
TRUE, &areaToFillFigure));
575 SkTScopedComPtr<IXpsOMPath> areaToFillPath;
576 HR(this->createPath(areaToFillFigure.get(), visuals, &areaToFillPath));
578 SkTScopedComPtr<IXpsOMImageBrush> areaToFillBrush;
579 HRM(this->fXpsFactory->CreateImageBrush(
image,
583 "Could not create brush for side of clamp.");
584 HRM(areaToFillBrush->SetTileMode(XPS_TILE_MODE_FLIPXY),
585 "Could not set tile mode for side of clamp.");
586 HRM(areaToFillPath->SetFillBrushLocal(areaToFillBrush.get()),
587 "Could not set brush for side of clamp");
592HRESULT SkXPSDevice::cornerOfClamp(
const SkRect& areaToFill,
594 IXpsOMVisualCollection* visuals) {
595 SkTScopedComPtr<IXpsOMGeometryFigure> areaToFillFigure;
596 HR(this->createXpsRect(areaToFill,
FALSE,
TRUE, &areaToFillFigure));
598 SkTScopedComPtr<IXpsOMPath> areaToFillPath;
599 HR(this->createPath(areaToFillFigure.get(), visuals, &areaToFillPath));
601 SkTScopedComPtr<IXpsOMBrush> areaToFillBrush;
602 HR(this->createXpsSolidColorBrush(
color, 0xFF, &areaToFillBrush));
603 HRM(areaToFillPath->SetFillBrushLocal(areaToFillBrush.get()),
604 "Could not set brush for corner of clamp.");
609static const XPS_TILE_MODE XTM_N = XPS_TILE_MODE_NONE;
610static const XPS_TILE_MODE XTM_T = XPS_TILE_MODE_TILE;
611static const XPS_TILE_MODE XTM_X = XPS_TILE_MODE_FLIPX;
612static const XPS_TILE_MODE XTM_Y = XPS_TILE_MODE_FLIPY;
613static const XPS_TILE_MODE XTM_XY = XPS_TILE_MODE_FLIPXY;
621 {XTM_N, XTM_T, XTM_Y, XTM_N},
622 {XTM_T, XTM_T, XTM_Y, XTM_N},
623 {XTM_X, XTM_X, XTM_XY, XTM_X},
624 {XTM_N, XTM_N, XTM_Y, XTM_N},
628 return gSkToXpsTileMode[(unsigned)
tmx][(
unsigned)
tmy];
631HRESULT SkXPSDevice::createXpsImageBrush(
636 IXpsOMTileBrush** xpsBrush) {
639 HRM(E_FAIL,
"Unable to encode bitmap as png.");
641 SkTScopedComPtr<IStream>
read;
642 HRM(SkIStream::CreateFromSkStream(
write.detachAsStream(), &
read),
643 "Could not create stream from png data.");
646 std::size(
L"/Documents/1/Resources/Images/" L_GUID_ID
L".png");
648 wchar_t id[GUID_ID_LEN];
649 HR(this->createId(
id, GUID_ID_LEN));
650 swprintf_s(
buffer,
size,
L"/Documents/1/Resources/Images/%s.png",
id);
652 SkTScopedComPtr<IOpcPartUri> imagePartUri;
653 HRM(this->fXpsFactory->CreatePartUri(
buffer, &imagePartUri),
654 "Could not create image part uri.");
656 SkTScopedComPtr<IXpsOMImageResource> imageResource;
657 HRM(this->fXpsFactory->CreateImageResource(
662 "Could not create image resource.");
664 XPS_RECT bitmapRect = {
666 static_cast<FLOAT
>(
bitmap.width()),
static_cast<FLOAT
>(
bitmap.height())
668 SkTScopedComPtr<IXpsOMImageBrush> xpsImageBrush;
669 HRM(this->fXpsFactory->CreateImageBrush(imageResource.get(),
670 &bitmapRect, &bitmapRect,
672 "Could not create image brush.");
677 HRM(xpsImageBrush->SetTileMode(SkToXpsTileMode(xy[0], xy[1])),
678 "Could not set image tile mode");
679 HRM(xpsImageBrush->SetOpacity(alpha / 255.0f),
680 "Could not set image opacity.");
681 HRM(xpsImageBrush->QueryInterface(xpsBrush),
"QI failed.");
685 const FLOAT BIG_F = SkScalarToFLOAT(
BIG);
690 SkTScopedComPtr<IXpsOMCanvas> brushCanvas;
691 HRM(this->fXpsFactory->CreateCanvas(&brushCanvas),
692 "Could not create image brush canvas.");
693 SkTScopedComPtr<IXpsOMVisualCollection> brushVisuals;
694 HRM(brushCanvas->GetVisuals(&brushVisuals),
695 "Could not get image brush canvas visuals collection.");
699 SkTScopedComPtr<IXpsOMGeometryFigure> centralFigure;
700 HR(this->createXpsRect(bitmapPoints,
FALSE,
TRUE, ¢ralFigure));
702 SkTScopedComPtr<IXpsOMPath> centralPath;
703 HR(this->createPath(centralFigure.get(),
706 HRM(xpsImageBrush->SetTileMode(XPS_TILE_MODE_FLIPXY),
707 "Could not set tile mode for image brush central path.");
708 HRM(centralPath->SetFillBrushLocal(xpsImageBrush.get()),
709 "Could not set fill brush for image brush central path.");
714 XPS_RECT leftImageViewBox = {
716 1.0,
static_cast<FLOAT
>(
bitmap.height()),
718 HR(this->sideOfClamp(leftArea, leftImageViewBox,
720 brushVisuals.get()));
723 XPS_RECT rightImageViewBox = {
724 bitmap.width() - 1.0f, 0.0f,
725 1.0f,
static_cast<FLOAT
>(
bitmap.height()),
727 HR(this->sideOfClamp(rightArea, rightImageViewBox,
729 brushVisuals.get()));
735 XPS_RECT topImageViewBox = {
737 static_cast<FLOAT
>(
bitmap.width()), 1.0,
739 HR(this->sideOfClamp(topArea, topImageViewBox,
741 brushVisuals.get()));
744 XPS_RECT bottomImageViewBox = {
745 0.0f,
bitmap.height() - 1.0f,
746 static_cast<FLOAT
>(
bitmap.width()), 1.0f,
748 HR(this->sideOfClamp(bottomArea, bottomImageViewBox,
750 brushVisuals.get()));
759 HR(this->cornerOfClamp(tlArea, tlColor, brushVisuals.get()));
763 HR(this->cornerOfClamp(trArea, trColor, brushVisuals.get()));
768 HR(this->cornerOfClamp(brArea, brColor, brushVisuals.get()));
772 HR(this->cornerOfClamp(blArea, blColor, brushVisuals.get()));
780 bound.x = BIG_F / -2;
781 bound.y = BIG_F / -2;
783 bound.height = BIG_F;
785 bound.x = BIG_F / -2;
788 bound.height =
static_cast<FLOAT
>(
bitmap.height());
791 bound.y = BIG_F / -2;
792 bound.width =
static_cast<FLOAT
>(
bitmap.width());
793 bound.height = BIG_F;
795 SkTScopedComPtr<IXpsOMVisualBrush> clampBrush;
796 HRM(this->fXpsFactory->CreateVisualBrush(&bound, &bound, &clampBrush),
797 "Could not create visual brush for image brush.");
798 HRM(clampBrush->SetVisualLocal(brushCanvas.get()),
799 "Could not set canvas on visual brush for image brush.");
800 HRM(clampBrush->SetTileMode(SkToXpsTileMode(xy[0], xy[1])),
801 "Could not set tile mode on visual brush for image brush.");
802 HRM(clampBrush->SetOpacity(alpha / 255.0f),
803 "Could not set opacity on visual brush for image brush.");
805 HRM(clampBrush->QueryInterface(xpsBrush),
"QI failed.");
808 SkTScopedComPtr<IXpsOMMatrixTransform> xpsMatrixToUse;
809 HR(this->createXpsTransform(localMatrix, &xpsMatrixToUse));
810 if (xpsMatrixToUse.get()) {
811 HRM((*xpsBrush)->SetTransformLocal(xpsMatrixToUse.get()),
812 "Could not set transform for image brush.");
820HRESULT SkXPSDevice::createXpsGradientStop(
const SkColor skColor,
822 IXpsOMGradientStop** xpsGradStop) {
823 XPS_COLOR gradStopXpsColor = xps_color(skColor);
824 HRM(this->fXpsFactory->CreateGradientStop(&gradStopXpsColor,
828 "Could not create gradient stop.");
835 IXpsOMMatrixTransform* xpsMatrix,
836 IXpsOMBrush** xpsBrush) {
837 XPS_POINT startPoint;
840 startPoint = xps_point(
info.fPoint[0]);
841 endPoint = xps_point(
info.fPoint[1]);
843 transform_offsets(
info.fColorOffsets,
info.fColorCount,
846 startPoint = xps_point(
info.fPoint[0], localMatrix);
847 endPoint = xps_point(
info.fPoint[1], localMatrix);
850 SkTScopedComPtr<IXpsOMGradientStop> gradStop0;
851 HR(createXpsGradientStop(
info.fColors[0],
852 info.fColorOffsets[0],
855 SkTScopedComPtr<IXpsOMGradientStop> gradStop1;
856 HR(createXpsGradientStop(
info.fColors[1],
857 info.fColorOffsets[1],
860 SkTScopedComPtr<IXpsOMLinearGradientBrush> gradientBrush;
861 HRM(this->fXpsFactory->CreateLinearGradientBrush(gradStop0.get(),
866 "Could not create linear gradient brush.");
868 HRM(gradientBrush->SetTransformLocal(xpsMatrix),
869 "Could not set transform on linear gradient brush.");
872 SkTScopedComPtr<IXpsOMGradientStopCollection> gradStopCollection;
873 HRM(gradientBrush->GetGradientStops(&gradStopCollection),
874 "Could not get linear gradient stop collection.");
875 for (
int i = 2;
i <
info.fColorCount; ++
i) {
876 SkTScopedComPtr<IXpsOMGradientStop> gradStop;
877 HR(createXpsGradientStop(
info.fColors[
i],
878 info.fColorOffsets[
i],
880 HRM(gradStopCollection->Append(gradStop.get()),
881 "Could not add linear gradient stop.");
884 HRM(gradientBrush->SetSpreadMethod(xps_spread_method((
SkTileMode)
info.fTileMode)),
885 "Could not set spread method of linear gradient.");
887 HRM(gradientBrush->SetOpacity(alpha / 255.0f),
888 "Could not set opacity of linear gradient brush.");
889 HRM(gradientBrush->QueryInterface<IXpsOMBrush>(xpsBrush),
"QI failed");
897 IXpsOMMatrixTransform* xpsMatrix,
898 IXpsOMBrush** xpsBrush) {
899 SkTScopedComPtr<IXpsOMGradientStop> gradStop0;
900 HR(createXpsGradientStop(
info.fColors[0],
901 info.fColorOffsets[0],
904 SkTScopedComPtr<IXpsOMGradientStop> gradStop1;
905 HR(createXpsGradientStop(
info.fColors[1],
906 info.fColorOffsets[1],
910 XPS_POINT centerPoint;
911 XPS_POINT gradientOrigin;
914 centerPoint = xps_point(
info.fPoint[0]);
915 gradientOrigin = xps_point(
info.fPoint[0]);
916 radiiSizes.width = SkScalarToFLOAT(
info.fRadius[0]);
917 radiiSizes.height = SkScalarToFLOAT(
info.fRadius[0]);
919 centerPoint = xps_point(
info.fPoint[0], localMatrix);
920 gradientOrigin = xps_point(
info.fPoint[0], localMatrix);
925 vec[0].
set(radius, 0);
926 vec[1].
set(0, radius);
932 radiiSizes.width = SkScalarToFLOAT(d0);
933 radiiSizes.height = SkScalarToFLOAT(d1);
936 SkTScopedComPtr<IXpsOMRadialGradientBrush> gradientBrush;
937 HRM(this->fXpsFactory->CreateRadialGradientBrush(gradStop0.get(),
943 "Could not create radial gradient brush.");
945 HRM(gradientBrush->SetTransformLocal(xpsMatrix),
946 "Could not set transform on radial gradient brush.");
949 SkTScopedComPtr<IXpsOMGradientStopCollection> gradStopCollection;
950 HRM(gradientBrush->GetGradientStops(&gradStopCollection),
951 "Could not get radial gradient stop collection.");
952 for (
int i = 2;
i <
info.fColorCount; ++
i) {
953 SkTScopedComPtr<IXpsOMGradientStop> gradStop;
954 HR(createXpsGradientStop(
info.fColors[
i],
955 info.fColorOffsets[
i],
957 HRM(gradStopCollection->Append(gradStop.get()),
958 "Could not add radial gradient stop.");
961 HRM(gradientBrush->SetSpreadMethod(xps_spread_method((
SkTileMode)
info.fTileMode)),
962 "Could not set spread method of radial gradient.");
964 HRM(gradientBrush->SetOpacity(alpha / 255.0f),
965 "Could not set opacity of radial gradient brush.");
966 HRM(gradientBrush->QueryInterface<IXpsOMBrush>(xpsBrush),
"QI failed.");
971HRESULT SkXPSDevice::createXpsBrush(
const SkPaint& skPaint,
975 if (
nullptr == shader) {
976 HR(this->createXpsSolidColorBrush(skPaint.
getColor(), 0xFF, brush));
981 auto shaderBase =
as_SB(shader);
984 auto colorShader =
static_cast<const SkColorShader*
>(shader);
986 HR(this->createXpsSolidColorBrush(colorShader->color(), alpha, brush));
988 }
else if (shaderBase->type() == SkShaderBase::ShaderType::kGradientBase) {
991 if (
info.fColorCount == 0) {
993 HR(this->createXpsSolidColorBrush(
color, 0xFF, brush));
1001 info.fColorOffsets = colorOffsets.get();
1002 shaderBase->asGradient(&
info, &localMatrix);
1004 if (1 ==
info.fColorCount) {
1007 HR(this->createXpsSolidColorBrush(
color, alpha, brush));
1011 if (parentTransform) {
1012 localMatrix.
preConcat(*parentTransform);
1014 SkTScopedComPtr<IXpsOMMatrixTransform> xpsMatrixToUse;
1015 HR(this->createXpsTransform(localMatrix, &xpsMatrixToUse));
1018 HR(this->createXpsLinearGradient(
info,
1021 xpsMatrixToUse.get(),
1026 if (gradientType == SkShaderBase::GradientType::kRadial) {
1027 HR(this->createXpsRadialGradient(
info,
1030 xpsMatrixToUse.get(),
1035 if (gradientType == SkShaderBase::GradientType::kConical) {
1039 if (gradientType == SkShaderBase::GradientType::kSweep) {
1049 if (parentTransform) {
1053 SkTScopedComPtr<IXpsOMTileBrush> tileBrush;
1054 HR(this->createXpsImageBrush(outTexture.
pixmap(), outMatrix, xy, skPaint.
getAlpha(),
1057 HRM(tileBrush->QueryInterface<IXpsOMBrush>(brush),
"QI failed.");
1059 HR(this->createXpsSolidColorBrush(skPaint.
getColor(), 0xFF, brush));
1065 const bool zeroWidth = (0 ==
paint.getStrokeWidth());
1068 return paint.getPathEffect() ||
1069 paint.getMaskFilter() ||
1071 (
matrix.hasPerspective() && !zeroWidth) ||
1080 IXpsOMGeometryFigure** xpsRect) {
1087 return this->createXpsQuad(
points,
stroke, fill, xpsRect);
1089HRESULT SkXPSDevice::createXpsQuad(
const SkPoint (&
points)[4],
1091 IXpsOMGeometryFigure** xpsQuad) {
1093 XPS_POINT startPoint = xps_point(
points[0]);
1096 HRM(this->fXpsFactory->CreateGeometryFigure(&startPoint, xpsQuad),
1097 "Could not create quad geometry figure.");
1100 XPS_SEGMENT_TYPE segmentTypes[3] = {
1101 XPS_SEGMENT_TYPE_LINE,
1102 XPS_SEGMENT_TYPE_LINE,
1103 XPS_SEGMENT_TYPE_LINE,
1107 FLOAT segmentData[6] = {
1108 SkScalarToFLOAT(
points[1].fX), SkScalarToFLOAT(
points[1].fY),
1109 SkScalarToFLOAT(
points[2].fX), SkScalarToFLOAT(
points[2].fY),
1110 SkScalarToFLOAT(
points[3].fX), SkScalarToFLOAT(
points[3].fY),
1114 BOOL segmentStrokes[3] = {
1119 HRM((*xpsQuad)->SetSegments(
1121 segmentTypes , segmentData, segmentStrokes),
1122 "Could not add segment data to quad.");
1125 HRM((*xpsQuad)->SetIsClosed(
stroke),
"Could not set quad close.");
1126 HRM((*xpsQuad)->SetIsFilled(fill),
"Could not set quad fill.");
1145void SkXPSDevice::drawPaint(
const SkPaint& origPaint) {
1155 this->internalDrawRect(r,
false, *fillPaint);
1158void SkXPSDevice::drawRect(
const SkRect& r,
1160 this->internalDrawRect(r,
true,
paint);
1163void SkXPSDevice::drawRRect(
const SkRRect& rr,
1170void SkXPSDevice::internalDrawRect(
const SkRect& r,
1174 if (this->isClipEmpty() || (
paint.getAlpha() == 0 &&
paint.isSrcOver())) {
1179 if (rect_must_be_pathed(
paint, this->localToDevice())) {
1188 SkTScopedComPtr<IXpsOMPath> shadedPath;
1189 HRVM(this->fXpsFactory->CreatePath(&shadedPath),
1190 "Could not create shaded path for rect.");
1193 SkTScopedComPtr<IXpsOMGeometry> shadedGeometry;
1194 HRVM(this->fXpsFactory->CreateGeometry(&shadedGeometry),
1195 "Could not create shaded geometry for rect.");
1198 HRVM(shadedPath->SetGeometryLocal(shadedGeometry.get()),
1199 "Could not set shaded geometry for rect.");
1204 HRV(this->shadePath(shadedPath.get(),
paint, this->localToDevice(), &fill, &
stroke));
1206 bool xpsTransformsPath =
true;
1208 if (transformRect && xpsTransformsPath) {
1209 SkTScopedComPtr<IXpsOMMatrixTransform> xpsTransform;
1210 HRV(this->createXpsTransform(this->localToDevice(), &xpsTransform));
1211 if (xpsTransform.get()) {
1212 HRVM(shadedGeometry->SetTransformLocal(xpsTransform.get()),
1213 "Could not set transform for rect.");
1215 xpsTransformsPath =
false;
1220 SkTScopedComPtr<IXpsOMGeometryFigure> rectFigure;
1228 if (!xpsTransformsPath && transformRect) {
1231 HRV(this->createXpsQuad(
points,
stroke, fill, &rectFigure));
1235 SkTScopedComPtr<IXpsOMGeometryFigureCollection> shadedFigures;
1236 HRVM(shadedGeometry->GetFigures(&shadedFigures),
1237 "Could not get shaded figures for rect.");
1240 HRVM(shadedFigures->Append(rectFigure.get()),
1241 "Could not add shaded figure for rect.");
1243 HRV(this->
clip(shadedPath.get()));
1246 SkTScopedComPtr<IXpsOMVisualCollection> currentVisuals;
1247 HRVM(this->fCurrentXpsCanvas->GetVisuals(¤tVisuals),
1248 "Could not get current visuals for rect.");
1249 HRVM(currentVisuals->Append(shadedPath.get()),
1250 "Could not add rect to current visuals.");
1257 IXpsOMGeometryFigure* figure,
1258 IXpsOMGeometryFigureCollection* figures) {
1261 (!segmentTypes.
empty() && !segmentData.
empty() && !segmentStrokes.
empty()));
1266 if (!segmentTypes.
empty() && !segmentData.
empty() && !segmentStrokes.
empty()) {
1268 HRM(figure->SetSegments(segmentTypes.
size(), segmentData.
size(),
1270 "Could not set path segments.");
1274 HRM(figure->SetIsClosed(
stroke),
"Could not set path closed.");
1275 HRM(figure->SetIsFilled(fill),
"Could not set path fill.");
1278 HRM(figures->Append(figure),
"Could not add path to geometry.");
1282HRESULT SkXPSDevice::addXpsPathGeometry(
1283 IXpsOMGeometryFigureCollection* xpsFigures,
1289 SkTScopedComPtr<IXpsOMGeometryFigure> xpsFigure;
1296 if (xpsFigure.get()) {
1297 HR(close_figure(segmentTypes, segmentData, segmentStrokes,
1299 xpsFigure.get() , xpsFigures));
1300 segmentTypes.
clear();
1301 segmentData.
clear();
1302 segmentStrokes.
clear();
1306 XPS_POINT startPoint = xps_point(
points[0]);
1308 HRM(this->fXpsFactory->CreateGeometryFigure(&startPoint,
1310 "Could not create path geometry figure.");
1314 if (iter.isCloseLine())
break;
1315 segmentTypes.
push_back(XPS_SEGMENT_TYPE_LINE);
1321 segmentTypes.
push_back(XPS_SEGMENT_TYPE_QUADRATIC_BEZIER);
1329 segmentTypes.
push_back(XPS_SEGMENT_TYPE_BEZIER);
1344 segmentTypes.
push_back(XPS_SEGMENT_TYPE_QUADRATIC_BEZIER);
1345 segmentData.
push_back(SkScalarToFLOAT(quads[2 *
i + 1].fX));
1346 segmentData.
push_back(SkScalarToFLOAT(quads[2 *
i + 1].fY));
1347 segmentData.
push_back(SkScalarToFLOAT(quads[2 *
i + 2].fX));
1348 segmentData.
push_back(SkScalarToFLOAT(quads[2 *
i + 2].fY));
1362 if (xpsFigure.get()) {
1363 HR(close_figure(segmentTypes, segmentData, segmentStrokes,
1365 xpsFigure.get(), xpsFigures));
1370void SkXPSDevice::convertToPpm(
const SkMaskFilter* filter,
1375 ppuScale->
set(fCurrentPixelsPerMeter.fX / fCurrentUnitsPerMeter.fX,
1376 fCurrentPixelsPerMeter.fY / fCurrentUnitsPerMeter.fY);
1378 matrix->postScale(ppuScale->
fX, ppuScale->
fY);
1388HRESULT SkXPSDevice::applyMask(
const SkMask& mask,
1390 IXpsOMPath* shadedPath) {
1392 SkTScopedComPtr<IXpsOMGeometry> shadedGeometry;
1393 HRM(shadedPath->GetGeometry(&shadedGeometry),
1394 "Could not get mask shaded geometry.");
1397 SkTScopedComPtr<IXpsOMGeometryFigureCollection> shadedFigures;
1398 HRM(shadedGeometry->GetFigures(&shadedFigures),
1399 "Could not get mask shaded figures.");
1415 SkTScopedComPtr<IXpsOMTileBrush> maskBrush;
1416 HR(this->createXpsImageBrush(pm,
m, xy, 0xFF, &maskBrush));
1417 HRM(shadedPath->SetOpacityMaskBrushLocal(maskBrush.get()),
1418 "Could not set mask.");
1421 this->fCurrentCanvasSize.fWidth, this->fCurrentCanvasSize.fHeight);
1422 SkTScopedComPtr<IXpsOMGeometryFigure> shadedFigure;
1423 HRM(this->createXpsRect(universeRect,
FALSE,
TRUE, &shadedFigure),
1424 "Could not create mask shaded figure.");
1425 HRM(shadedFigures->Append(shadedFigure.get()),
1426 "Could not add mask shaded figure.");
1428 HR(this->
clip(shadedPath));
1431 SkTScopedComPtr<IXpsOMVisualCollection> currentVisuals;
1432 HRM(this->fCurrentXpsCanvas->GetVisuals(¤tVisuals),
1433 "Could not get mask current visuals.");
1434 HRM(currentVisuals->Append(shadedPath),
1435 "Could not add masked shaded path to current visuals.");
1440HRESULT SkXPSDevice::shadePath(IXpsOMPath* shadedPath,
1456 SkTScopedComPtr<IXpsOMBrush> fillBrush;
1457 HR(this->createXpsBrush(shaderPaint, &fillBrush, &
matrix));
1458 HRM(shadedPath->SetFillBrushLocal(fillBrush.get()),
1459 "Could not set fill for shaded path.");
1464 SkTScopedComPtr<IXpsOMBrush> strokeBrush;
1465 HR(this->createXpsBrush(shaderPaint, &strokeBrush, &
matrix));
1466 HRM(shadedPath->SetStrokeBrushLocal(strokeBrush.get()),
1467 "Could not set stroke brush for shaded path.");
1468 HRM(shadedPath->SetStrokeThickness(
1470 "Could not set shaded path stroke thickness.");
1474 SkTScopedComPtr<IXpsOMDashCollection> dashes;
1475 HRM(shadedPath->GetStrokeDashes(&dashes),
1476 "Could not set dashes for shaded path.");
1480 HRM(dashes->Append(&dash),
"Could not add dashes to shaded path.");
1481 HRM(shadedPath->SetStrokeDashOffset(-2.0),
1482 "Could not set dash offset for shaded path.");
1490 bool pathIsMutable) {
1494 if (this->isClipEmpty() || (
paint->getAlpha() == 0 &&
paint->isSrcOver())) {
1499 const bool paintHasPathEffect =
paint->getPathEffect()
1504 SkPath* skeletalPath =
const_cast<SkPath*
>(&platonicPath);
1507 SkPath* fillablePath = skeletalPath;
1508 if (paintHasPathEffect) {
1509 if (!pathIsMutable) {
1510 fillablePath = &modifiedPath;
1511 pathIsMutable =
true;
1526 SkTScopedComPtr<IXpsOMPath> shadedPath;
1527 HRVM(this->fXpsFactory->CreatePath(&shadedPath),
1528 "Could not create shaded path for path.");
1531 SkTScopedComPtr<IXpsOMGeometry> shadedGeometry;
1532 HRVM(this->fXpsFactory->CreateGeometry(&shadedGeometry),
1533 "Could not create shaded geometry for path.");
1536 HRVM(shadedPath->SetGeometryLocal(shadedGeometry.get()),
1537 "Could not add the shaded geometry to shaded path.");
1551 HRV(this->shadePath(shadedPath.get(),
1553 this->localToDevice(),
1561 this->convertToPpm(filter,
1564 this->devClipBounds(),
1568 SkPath* pixelPath = pathIsMutable ? fillablePath : &modifiedPath;
1590 mask = &rasteredMask;
1594 if (
as_MFB(filter)->filterMask(&filteredMask, rasteredMask,
matrix,
nullptr)) {
1595 mask = &filteredMask;
1600 HRV(this->applyMask(*mask, ppuScale, shadedPath.get()));
1606 SkTScopedComPtr<IXpsOMGeometryFigureCollection> shadedFigures;
1607 HRVM(shadedGeometry->GetFigures(&shadedFigures),
1608 "Could not get shaded figures for shaded path.");
1610 bool xpsTransformsPath =
true;
1613 SkPath* xpsCompatiblePath = fillablePath;
1614 XPS_FILL_RULE xpsFillRule;
1617 xpsFillRule = XPS_FILL_RULE_NONZERO;
1620 xpsFillRule = XPS_FILL_RULE_EVENODD;
1624 if (!pathIsMutable) {
1625 xpsCompatiblePath = &modifiedPath;
1626 pathIsMutable =
true;
1628 if (!
Simplify(*fillablePath, xpsCompatiblePath)) {
1629 SkDEBUGF(
"Could not simplify inverse winding path.");
1637 this->fCurrentCanvasSize.fWidth,
1638 this->fCurrentCanvasSize.fHeight);
1639 SkTScopedComPtr<IXpsOMGeometryFigure> addOneFigure;
1640 HRV(this->createXpsRect(universe,
FALSE,
TRUE, &addOneFigure));
1641 HRVM(shadedFigures->Append(addOneFigure.get()),
1642 "Could not add even-odd flip figure to shaded path.");
1643 xpsTransformsPath =
false;
1644 xpsFillRule = XPS_FILL_RULE_EVENODD;
1650 HRVM(shadedGeometry->SetFillRule(xpsFillRule),
1651 "Could not set fill rule for shaded path.");
1654 if (xpsTransformsPath) {
1655 SkTScopedComPtr<IXpsOMMatrixTransform> xpsTransform;
1656 HRV(this->createXpsTransform(
matrix, &xpsTransform));
1658 if (xpsTransform.get()) {
1659 HRVM(shadedGeometry->SetTransformLocal(xpsTransform.get()),
1660 "Could not set transform on shaded path.");
1662 xpsTransformsPath =
false;
1666 SkPath* devicePath = xpsCompatiblePath;
1667 if (!xpsTransformsPath) {
1669 devicePath = pathIsMutable ? xpsCompatiblePath : &modifiedPath;
1672 HRV(this->addXpsPathGeometry(shadedFigures.get(),
1673 stroke, fill, *devicePath));
1675 HRV(this->
clip(shadedPath.get()));
1678 SkTScopedComPtr<IXpsOMVisualCollection> currentVisuals;
1679 HRVM(this->fCurrentXpsCanvas->GetVisuals(¤tVisuals),
1680 "Could not get current visuals for shaded path.");
1681 HRVM(currentVisuals->Append(shadedPath.get()),
1682 "Could not add shaded path to current visuals.");
1686 if (this->cs().isWideOpen()) {
1693 return this->clipToPath(xpsVisual,
clipPath, XPS_FILL_RULE_EVENODD);
1695HRESULT SkXPSDevice::clipToPath(IXpsOMVisual* xpsVisual,
1697 XPS_FILL_RULE fillRule) {
1699 SkTScopedComPtr<IXpsOMGeometry> clipGeometry;
1700 HRM(this->fXpsFactory->CreateGeometry(&clipGeometry),
1701 "Could not create clip geometry.");
1704 SkTScopedComPtr<IXpsOMGeometryFigureCollection> clipFigures;
1705 HRM(clipGeometry->GetFigures(&clipFigures),
1706 "Could not get the clip figures.");
1709 HR(this->addXpsPathGeometry(
1713 HRM(clipGeometry->SetFillRule(fillRule),
1714 "Could not set fill rule.");
1715 HRM(xpsVisual->SetClipGeometryLocal(clipGeometry.get()),
1716 "Could not set clip geometry.");
1721HRESULT SkXPSDevice::CreateTypefaceUse(
const SkFont&
font,
1722 TypefaceUse** typefaceUse) {
1727 for (TypefaceUse& current : *this->fTopTypefaces) {
1728 if (current.typefaceId == typefaceID) {
1729 *typefaceUse = ¤t;
1736 XPS_FONT_EMBEDDING embedding = XPS_FONT_EMBEDDING_RESTRICTED;
1738 SkTScopedComPtr<IStream> fontStream;
1740 std::unique_ptr<SkStreamAsset> fontData = typeface->
openStream(&ttcIndex);
1745 HRM(SkIStream::CreateFromSkStream(fontData->duplicate(), &fontStream),
1746 "Could not create font stream.");
1749 std::size(
L"/Resources/Fonts/" L_GUID_ID
L".odttf");
1751 wchar_t id[GUID_ID_LEN];
1752 HR(this->createId(
id, GUID_ID_LEN));
1753 swprintf_s(
buffer,
size,
L"/Resources/Fonts/%s.odttf",
id);
1755 SkTScopedComPtr<IOpcPartUri> partUri;
1756 HRM(this->fXpsFactory->CreatePartUri(
buffer, &partUri),
1757 "Could not create font resource part uri.");
1759 SkTScopedComPtr<IXpsOMFontResource> xpsFontResource;
1760 HRM(this->fXpsFactory->CreateFontResource(fontStream.get(),
1765 "Could not create font resource.");
1768 const uint8_t*
data = (
const uint8_t*)fontData->getMemoryBase();
1769 bool isTTC = (
data &&
1775 TypefaceUse& newTypefaceUse = this->fTopTypefaces->emplace_back(
1777 isTTC ? ttcIndex : -1,
1778 std::move(fontData),
1779 std::move(xpsFontResource),
1782 *typefaceUse = &newTypefaceUse;
1786HRESULT SkXPSDevice::AddGlyphs(IXpsOMObjectFactory* xpsFactory,
1787 IXpsOMCanvas* canvas,
1788 const TypefaceUse*
font,
1790 XPS_GLYPH_INDEX* xpsGlyphs,
1791 UINT32 xpsGlyphsLen,
1794 XPS_STYLE_SIMULATION sims,
1797 SkTScopedComPtr<IXpsOMGlyphs>
glyphs;
1798 HRM(xpsFactory->CreateGlyphs(
font->xpsFont.get(), &
glyphs),
"Could not create glyphs.");
1799 HRM(
glyphs->SetFontFaceIndex(
font->ttcIndex),
"Could not set glyph font face index.");
1803 bool useCanvasForClip;
1805 origin->x += SkScalarToFLOAT(
transform.getTranslateX());
1806 origin->y += SkScalarToFLOAT(
transform.getTranslateY());
1807 useCanvasForClip =
false;
1809 SkTScopedComPtr<IXpsOMMatrixTransform> xpsMatrixToUse;
1810 HR(this->createXpsTransform(
transform, &xpsMatrixToUse));
1811 if (xpsMatrixToUse.get()) {
1812 HRM(
glyphs->SetTransformLocal(xpsMatrixToUse.get()),
1813 "Could not set transform matrix.");
1814 useCanvasForClip =
true;
1816 SkDEBUGFAIL(
"Attempt to add glyphs in perspective.");
1817 useCanvasForClip =
false;
1821 SkTScopedComPtr<IXpsOMGlyphsEditor> glyphsEditor;
1822 HRM(
glyphs->GetGlyphsEditor(&glyphsEditor),
"Could not get glyph editor.");
1825 HRM(glyphsEditor->SetUnicodeString(
text),
1826 "Could not set unicode string.");
1830 HRM(glyphsEditor->SetGlyphIndices(xpsGlyphsLen, xpsGlyphs),
1831 "Could not set glyphs.");
1834 HRM(glyphsEditor->ApplyEdits(),
"Could not apply glyph edits.");
1836 SkTScopedComPtr<IXpsOMBrush> xpsFillBrush;
1837 HR(this->createXpsBrush(
1840 useCanvasForClip ?
nullptr : &
transform));
1842 HRM(
glyphs->SetFillBrushLocal(xpsFillBrush.get()),
1843 "Could not set fill brush.");
1845 HRM(
glyphs->SetOrigin(origin),
"Could not set glyph origin.");
1847 HRM(
glyphs->SetFontRenderingEmSize(fontSize),
1848 "Could not set font size.");
1850 HRM(
glyphs->SetStyleSimulations(sims),
1851 "Could not set style simulations.");
1853 SkTScopedComPtr<IXpsOMVisualCollection> visuals;
1854 HRM(canvas->GetVisuals(&visuals),
"Could not get glyph canvas visuals.");
1856 if (!useCanvasForClip) {
1857 HR(this->
clip(glyphs.get()));
1858 HRM(visuals->Append(
glyphs.get()),
"Could not add glyphs to canvas.");
1860 SkTScopedComPtr<IXpsOMCanvas> glyphCanvas;
1861 HRM(this->fXpsFactory->CreateCanvas(&glyphCanvas),
1862 "Could not create glyph canvas.");
1864 SkTScopedComPtr<IXpsOMVisualCollection> glyphCanvasVisuals;
1865 HRM(glyphCanvas->GetVisuals(&glyphCanvasVisuals),
1866 "Could not get glyph visuals collection.");
1868 HRM(glyphCanvasVisuals->Append(
glyphs.get()),
1869 "Could not add glyphs to page.");
1870 HR(this->
clip(glyphCanvas.get()));
1872 HRM(visuals->Append(glyphCanvas.get()),
1873 "Could not add glyph canvas to page.");
1881 return matrix.hasPerspective()
1884 ||
paint.getMaskFilter()
1888void SkXPSDevice::onDrawGlyphRunList(
SkCanvas*,
1893 for (
const auto&
run : glyphRunList) {
1895 size_t glyphCount =
run.glyphsIDs().size();
1898 if (!glyphCount || !glyphIDs ||
font.getSize() <= 0) {
1902 TypefaceUse* typeface;
1903 if (
FAILED(CreateTypefaceUse(
font, &typeface)) ||
1904 text_must_be_pathed(
paint, this->localToDevice())) {
1917 FLOAT centemPerUnit = 100.0f / SkScalarToFLOAT(
font.getSize());
1919 size_t numGlyphs = typeface->glyphsUsed.size();
1920 size_t actualGlyphCount = 0;
1922 for (
size_t i = 0;
i < glyphCount; ++
i) {
1923 if (numGlyphs <= glyphIDs[
i]) {
1927 XPS_GLYPH_INDEX& xpsGlyph = xpsGlyphs[actualGlyphCount++];
1928 xpsGlyph.index = glyphIDs[
i];
1929 xpsGlyph.advanceWidth = 0.0f;
1932 typeface->glyphsUsed.set(xpsGlyph.index);
1935 if (actualGlyphCount == 0) {
1939 XPS_POINT origin = {
1940 glyphRunList.origin().x(),
1941 glyphRunList.origin().y(),
1944 HRV(AddGlyphs(this->fXpsFactory.get(),
1945 this->fCurrentXpsCanvas.get(),
1948 xpsGlyphs.get(), actualGlyphCount,
1950 SkScalarToFLOAT(
font.getSize()),
1951 XPS_STYLE_SIMULATION_NONE,
1952 this->localToDevice(),
1958 SkXPSDevice* that =
static_cast<SkXPSDevice*
>(dev);
1959 SkASSERT(that->fTopTypefaces == this->fTopTypefaces);
1961 SkTScopedComPtr<IXpsOMMatrixTransform> xpsTransform;
1963 "Could not create layer transform.");
1964 HRVM(that->fCurrentXpsCanvas->SetTransformLocal(xpsTransform.get()),
1965 "Could not set layer transform.");
1968 SkTScopedComPtr<IXpsOMVisualCollection> currentVisuals;
1969 HRVM(this->fCurrentXpsCanvas->GetVisuals(¤tVisuals),
1970 "Could not get current visuals for layer.");
1971 HRVM(currentVisuals->Append(that->fCurrentXpsCanvas.get()),
1972 "Could not add layer to current visuals.");
1977 dev->fXpsFactory.
reset(SkRefComPtr(fXpsFactory.get()));
1978 dev->fCurrentCanvasSize = this->fCurrentCanvasSize;
1979 dev->fCurrentUnitsPerMeter = this->fCurrentUnitsPerMeter;
1980 dev->fCurrentPixelsPerMeter = this->fCurrentPixelsPerMeter;
1981 dev->fTopTypefaces = this->fTopTypefaces;
2011 if (!srcBounds.
intersect(bitmapBounds)) {
2014 matrix.mapRect(&actualDst, srcBounds);
2021 if (!bitmapShader) {
return; }
2024 paintWithShader.setShader(std::move(bitmapShader));
2025 this->drawRect(actualDst, paintWithShader);
static constexpr SkColor kColor
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
SkAssertResult(font.textToGlyphs("Hello", 5, SkTextEncoding::kUTF8, glyphs, std::size(glyphs))==count)
static const int points[]
#define SkDEBUGFAIL(message)
void SkClipStack_AsPath(const SkClipStack &cs, SkPath *path)
#define SkColorGetR(color)
#define SkColorGetG(color)
#define SkColorGetA(color)
#define SkColorGetB(color)
#define SkEndian_SwapBE32(n)
#define SkEndian_SwapBE16(n)
static bool read(SkStream *stream, void *buffer, size_t amount)
@ kNever_SkCopyPixelsMode
never copy src pixels (even if they are marked mutable)
sk_sp< SkShader > SkMakeBitmapShaderForPaint(const SkPaint &paint, const SkBitmap &src, SkTileMode, SkTileMode, const SkSamplingOptions &, const SkMatrix *localMatrix, SkCopyPixelsMode)
static SkImage_Base * as_IB(SkImage *image)
SK_API void sk_free(void *)
static void * sk_malloc_throw(size_t size)
SK_API void * sk_realloc_throw(void *buffer, size_t size)
SkMaskFilterBase * as_MFB(SkMaskFilter *mf)
std::unique_ptr< uint8_t, SkFunctionObject< SkMaskBuilder::FreeImage > > SkAutoMaskFreeImage
bool SK_API Simplify(const SkPath &path, SkPath *result)
static SkPath clip(const SkPath &path, const SkHalfPlane &plane)
#define SkScalarInvert(x)
static bool SkScalarNearlyZero(SkScalar x, SkScalar tolerance=SK_ScalarNearlyZero)
#define SkScalarToFloat(x)
SkShaderBase * as_SB(SkShader *shader)
static constexpr int kSkTileModeCount
constexpr uint32_t SkToU32(S x)
const SkPixmap & pixmap() const
SkMatrix getRelativeTransform(const SkDevice &) const
static bool DrawToMask(const SkPath &devPath, const SkIRect &clipBounds, const SkMaskFilter *, const SkMatrix *filterMatrix, SkMaskBuilder *dst, SkMaskBuilder::CreateMode mode, SkStrokeRec::InitStyle style)
bool asLegacyBitmap(SkBitmap *bitmap, LegacyBitmapMode legacyBitmapMode=kRO_LegacyBitmapMode) const
static SkMatrix RectToRect(const SkRect &src, const SkRect &dst, ScaleToFit mode=kFill_ScaleToFit)
static constexpr int kATransY
vertical translation
SkMatrix & postConcat(const SkMatrix &other)
static constexpr int kAScaleY
vertical scale factor
static constexpr int kASkewX
horizontal skew factor
void mapVectors(SkVector dst[], const SkVector src[], int count) const
static constexpr int kATransX
horizontal translation
static constexpr int kAScaleX
horizontal scale factor
static constexpr int kASkewY
vertical skew factor
SkMatrix & preConcat(const SkMatrix &other)
void setStyle(Style style)
@ kStroke_Style
set to stroke geometry
@ kFill_Style
set to fill geometry
@ kStrokeAndFill_Style
sets to stroke and fill geometry
void setPathEffect(sk_sp< SkPathEffect > pathEffect)
SkScalar getStrokeWidth() const
@ kMiter_Join
extends to miter limit
SkShader * getShader() const
void setStrokeWidth(SkScalar width)
SkPathFillType getFillType() const
void setFillType(SkPathFillType ft)
void transform(const SkMatrix &matrix, SkPath *dst, SkApplyPerspectiveClip pc=SkApplyPerspectiveClip::kYes) const
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
SkImage * isAImage(SkMatrix *localMatrix, SkTileMode xy[2]) const
void push_back(const T &v)
SkTypefaceID uniqueID() const
std::unique_ptr< SkStreamAsset > openStream(int *ttcIndex) const
void reset(T *ptr=nullptr)
static float max(float r, float g, float b)
static void drawPath(SkPath &path, SkCanvas *canvas, SkColor color, const SkRect &clip, SkPaint::Cap cap, SkPaint::Join join, SkPaint::Style style, SkPathFillType fill, SkScalar strokeWidth)
static constexpr skcms_TransferFunction kLinear
SK_API bool Encode(SkWStream *dst, const SkPixmap &src, const Options &options)
unsigned useCenter Optional< SkMatrix > matrix
clipRect(r.rect, r.opAA.op(), r.opAA.aa())) template<> void Draw
sk_sp< const SkImage > image
clipPath(r.path, r.opAA.op(), r.opAA.aa())) DRAW(ClipRRect
sk_sp< SkBlender > blender SkRect rect
PODArray< SkColor > colors
SkSamplingOptions sampling
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir path
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive mode
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
font
Font Metadata and Metrics.
SK_API bool FillPathWithPaint(const SkPath &src, const SkPaint &paint, SkPath *dst, const SkRect *cullRect, SkScalar resScale=1)
static SkColor4f transform(SkColor4f c, SkColorSpace *src, SkColorSpace *dst)
void write(SkWStream *wStream, const T &text)
int32_t fBottom
larger y-axis bounds
constexpr int32_t height() const
int32_t fTop
smaller y-axis bounds
constexpr int32_t width() const
int32_t fLeft
smaller x-axis bounds
int32_t fRight
larger x-axis bounds
static SkImageInfo MakeA8(int width, int height)
@ kComputeBoundsAndRenderImage_CreateMode
compute bounds, alloc image and render into it
@ kA8_Format
8bits per pixel mask (e.g. antialiasing)
uint8_t const *const fImage
void set(float x, float y)
static SkRect Make(const SkISize &size)
SkScalar fBottom
larger y-axis bounds
bool intersect(const SkRect &r)
SkScalar fLeft
smaller x-axis bounds
SkScalar fRight
larger x-axis bounds
bool contains(SkScalar x, SkScalar y) const
static constexpr SkRect MakeSize(const SkSize &size)
static constexpr SkRect MakeLTRB(float l, float t, float r, float b)
SkScalar fTop
smaller y-axis bounds
std::shared_ptr< const fml::Mapping > data