| Index: src/device/xps/SkXPSDevice.cpp
|
| ===================================================================
|
| --- src/device/xps/SkXPSDevice.cpp (revision 9016)
|
| +++ src/device/xps/SkXPSDevice.cpp (working copy)
|
| @@ -22,6 +22,7 @@
|
| #include "SkData.h"
|
| #include "SkDraw.h"
|
| #include "SkDrawProcs.h"
|
| +#include "SkEndian.h"
|
| #include "SkFontHost.h"
|
| #include "SkGlyphCache.h"
|
| #include "SkHRESULT.h"
|
| @@ -31,12 +32,14 @@
|
| #include "SkPaint.h"
|
| #include "SkPoint.h"
|
| #include "SkRasterizer.h"
|
| +#include "SkSFNTHeader.h"
|
| #include "SkShader.h"
|
| #include "SkSize.h"
|
| #include "SkStream.h"
|
| #include "SkTDArray.h"
|
| #include "SkTLazy.h"
|
| #include "SkTScopedComPtr.h"
|
| +#include "SkTTCFHeader.h"
|
| #include "SkTypefacePriv.h"
|
| #include "SkUtils.h"
|
| #include "SkXPSDevice.h"
|
| @@ -80,6 +83,7 @@
|
| guid.Data4[6],
|
| 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.
|
| @@ -179,10 +183,10 @@
|
| "Could not create thumbnail generator.");
|
|
|
| SkTScopedComPtr<IOpcPartUri> partUri;
|
| - static const size_t size = SK_MAX(
|
| + static const size_t size = SkTUMax<
|
| SK_ARRAY_COUNT(L"/Documents/1/Metadata/.png") + SK_DIGITS_IN(pageNum),
|
| SK_ARRAY_COUNT(L"/Metadata/" L_GUID_ID L".png")
|
| - );
|
| + >::value;
|
| wchar_t buffer[size];
|
| if (pageNum > 0) {
|
| swprintf_s(buffer, size, L"/Documents/1/Metadata/%u.png", pageNum);
|
| @@ -334,18 +338,20 @@
|
| SkTDArray<unsigned short> keepList;
|
| current->glyphsUsed->exportTo(&keepList);
|
|
|
| + int ttcCount = (current->ttcIndex + 1);
|
| +
|
| //The following are declared with the types required by CreateFontPackage.
|
| - unsigned char *puchFontPackageBuffer;
|
| - unsigned long pulFontPackageBufferSize;
|
| - unsigned long pulBytesWritten;
|
| + unsigned char *fontPackageBufferRaw = NULL;
|
| + unsigned long fontPackageBufferSize;
|
| + unsigned long bytesWritten;
|
| unsigned long result = CreateFontPackage(
|
| (unsigned char *) current->fontData->getMemoryBase(),
|
| (unsigned long) current->fontData->getLength(),
|
| - &puchFontPackageBuffer,
|
| - &pulFontPackageBufferSize,
|
| - &pulBytesWritten,
|
| - TTFCFP_FLAGS_SUBSET | TTFCFP_FLAGS_GLYPHLIST,// | TTFCFP_FLAGS_TTC,
|
| - 0,//TTC index
|
| + &fontPackageBufferRaw,
|
| + &fontPackageBufferSize,
|
| + &bytesWritten,
|
| + TTFCFP_FLAGS_SUBSET | TTFCFP_FLAGS_GLYPHLIST | (ttcCount > 0 ? TTFCFP_FLAGS_TTC : 0),
|
| + current->ttcIndex,
|
| TTFCFP_SUBSET,
|
| 0,
|
| 0,
|
| @@ -356,15 +362,51 @@
|
| sk_realloc_throw,
|
| sk_free,
|
| NULL);
|
| + SkAutoTMalloc<unsigned char> fontPackageBuffer(fontPackageBufferRaw);
|
| if (result != NO_ERROR) {
|
| SkDEBUGF(("CreateFontPackage Error %lu", result));
|
| return E_UNEXPECTED;
|
| }
|
|
|
| - SkMemoryStream* newStream = new SkMemoryStream;
|
| - newStream->setMemoryOwned(puchFontPackageBuffer, pulBytesWritten);
|
| + // If it was originally a ttc, keep it a ttc.
|
| + // CreateFontPackage over-allocates, realloc usually decreases the size substantially.
|
| + size_t extra;
|
| + if (ttcCount > 0) {
|
| + // Create space for a ttc header.
|
| + extra = sizeof(SkTTCFHeader) + (ttcCount * sizeof(SK_OT_ULONG));
|
| + fontPackageBuffer.realloc(bytesWritten + extra);
|
| + //overlap is certain, use memmove
|
| + memmove(fontPackageBuffer.get() + extra, fontPackageBuffer.get(), bytesWritten);
|
| +
|
| + // Write the ttc header.
|
| + SkTTCFHeader* ttcfHeader = reinterpret_cast<SkTTCFHeader*>(fontPackageBuffer.get());
|
| + ttcfHeader->ttcTag = SkTTCFHeader::TAG;
|
| + ttcfHeader->version = SkTTCFHeader::version_1;
|
| + ttcfHeader->numOffsets = SkEndian_SwapBE32(ttcCount);
|
| + SK_OT_ULONG* offsetPtr = SkTAfter<SK_OT_ULONG>(ttcfHeader);
|
| + for (int i = 0; i < ttcCount; ++i, ++offsetPtr) {
|
| + *offsetPtr = SkEndian_SwapBE32(extra);
|
| + }
|
| +
|
| + // Fix up offsets in sfnt table entries.
|
| + SkSFNTHeader* sfntHeader = SkTAddOffset<SkSFNTHeader>(fontPackageBuffer.get(), extra);
|
| + int numTables = SkEndian_SwapBE16(sfntHeader->numTables);
|
| + SkSFNTHeader::TableDirectoryEntry* tableDirectory =
|
| + SkTAfter<SkSFNTHeader::TableDirectoryEntry>(sfntHeader);
|
| + for (int i = 0; i < numTables; ++i, ++tableDirectory) {
|
| + tableDirectory->offset = SkEndian_SwapBE32(
|
| + SkEndian_SwapBE32(tableDirectory->offset) + extra);
|
| + }
|
| + } else {
|
| + extra = 0;
|
| + fontPackageBuffer.realloc(bytesWritten);
|
| + }
|
| +
|
| + SkAutoTUnref<SkMemoryStream> newStream(new SkMemoryStream());
|
| + newStream->setMemoryOwned(fontPackageBuffer.detach(), bytesWritten + extra);
|
| +
|
| SkTScopedComPtr<IStream> newIStream;
|
| - SkIStream::CreateFromSkStream(newStream, true, &newIStream);
|
| + SkIStream::CreateFromSkStream(newStream.detach(), true, &newIStream);
|
|
|
| XPS_FONT_EMBEDDING embedding;
|
| HRM(current->xpsFont->GetEmbeddingOption(&embedding),
|
| @@ -2034,7 +2076,8 @@
|
| XPS_FONT_EMBEDDING embedding = XPS_FONT_EMBEDDING_RESTRICTED;
|
|
|
| SkTScopedComPtr<IStream> fontStream;
|
| - SkStream* fontData = typeface->openStream(NULL);
|
| + int ttcIndex;
|
| + SkStream* fontData = typeface->openStream(&ttcIndex);
|
| HRM(SkIStream::CreateFromSkStream(fontData, true, &fontStream),
|
| "Could not create font stream.");
|
|
|
| @@ -2057,8 +2100,15 @@
|
| &xpsFontResource),
|
| "Could not create font resource.");
|
|
|
| + //TODO: change openStream to return -1 for non-ttc, get rid of this.
|
| + uint8_t* data = (uint8_t*)fontData->getMemoryBase();
|
| + bool isTTC = (data &&
|
| + fontData->getLength() >= sizeof(SkTTCFHeader) &&
|
| + ((SkTTCFHeader*)data)->ttcTag == SkTTCFHeader::TAG);
|
| +
|
| TypefaceUse& newTypefaceUse = this->fTypefaces.push_back();
|
| newTypefaceUse.typefaceId = typefaceID;
|
| + newTypefaceUse.ttcIndex = isTTC ? ttcIndex : -1;
|
| newTypefaceUse.fontData = fontData;
|
| newTypefaceUse.xpsFont = xpsFontResource.release();
|
|
|
| @@ -2074,7 +2124,7 @@
|
| HRESULT SkXPSDevice::AddGlyphs(const SkDraw& d,
|
| IXpsOMObjectFactory* xpsFactory,
|
| IXpsOMCanvas* canvas,
|
| - IXpsOMFontResource* font,
|
| + TypefaceUse* font,
|
| LPCWSTR text,
|
| XPS_GLYPH_INDEX* xpsGlyphs,
|
| UINT32 xpsGlyphsLen,
|
| @@ -2084,7 +2134,8 @@
|
| const SkMatrix& transform,
|
| const SkPaint& paint) {
|
| SkTScopedComPtr<IXpsOMGlyphs> glyphs;
|
| - HRM(xpsFactory->CreateGlyphs(font, &glyphs), "Could not create glyphs.");
|
| + HRM(xpsFactory->CreateGlyphs(font->xpsFont, &glyphs), "Could not create glyphs.");
|
| + HRM(glyphs->SetFontFaceIndex(font->ttcIndex), "Could not set glyph font face index.");
|
|
|
| //XPS uses affine transformations for everything...
|
| //...except positioning text.
|
| @@ -2282,7 +2333,7 @@
|
| HRV(AddGlyphs(d,
|
| this->fXpsFactory.get(),
|
| this->fCurrentXpsCanvas.get(),
|
| - typeface->xpsFont,
|
| + typeface,
|
| NULL,
|
| procs.xpsGlyphs.begin(), procs.xpsGlyphs.count(),
|
| &origin,
|
| @@ -2334,7 +2385,7 @@
|
| HRV(AddGlyphs(d,
|
| this->fXpsFactory.get(),
|
| this->fCurrentXpsCanvas.get(),
|
| - typeface->xpsFont,
|
| + typeface,
|
| NULL,
|
| procs.xpsGlyphs.begin(), procs.xpsGlyphs.count(),
|
| &origin,
|
|
|