summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/experimental/PdfViewer/SkPdfFont.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/experimental/PdfViewer/SkPdfFont.h')
-rw-r--r--chromium/third_party/skia/experimental/PdfViewer/SkPdfFont.h479
1 files changed, 479 insertions, 0 deletions
diff --git a/chromium/third_party/skia/experimental/PdfViewer/SkPdfFont.h b/chromium/third_party/skia/experimental/PdfViewer/SkPdfFont.h
new file mode 100644
index 00000000000..cc490553d1a
--- /dev/null
+++ b/chromium/third_party/skia/experimental/PdfViewer/SkPdfFont.h
@@ -0,0 +1,479 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+// TODO(edisonn): this file not commented much on purpose.
+// It will probably need heavy refactoring soon anyway to support all encodings, fonts and
+// proper text sizing and spacing
+
+#ifndef SkPdfFont_DEFINED
+#define SkPdfFont_DEFINED
+
+#include "SkPdfContext.h"
+#include "SkPdfHeaders_autogen.h"
+#include "SkPdfMapper_autogen.h"
+#include "SkPdfUtils.h"
+#include "SkTypeface.h"
+#include "SkTDict.h"
+#include "SkUtils.h"
+
+class SkPdfType0Font;
+class SkPdfType1Font;
+class SkPdfType3Font;
+class SkPdfTrueTypeFont;
+class SkPdfMultiMasterFont;
+class SkPdfFont;
+
+struct SkPdfStandardFontEntry {
+ // We don't own this pointer!
+ const char* fName;
+ bool fIsBold;
+ bool fIsItalic;
+ SkPdfStandardFontEntry()
+ : fName(NULL),
+ fIsBold(false),
+ fIsItalic(false) {}
+
+ SkPdfStandardFontEntry(const char* name, bool bold, bool italic)
+ : fName(name),
+ fIsBold(bold),
+ fIsItalic(italic) {}
+};
+
+SkTDict<SkPdfStandardFontEntry>& getStandardFonts();
+SkTypeface* SkTypefaceFromPdfStandardFont(const char* fontName, bool bold, bool italic);
+SkPdfFont* fontFromName(SkPdfNativeDoc* doc, SkPdfNativeObject* obj, const char* fontName);
+
+struct SkUnencodedText {
+ void* text;
+ int len;
+
+public:
+ SkUnencodedText(const SkPdfString* obj) {
+ text = (void*)obj->c_str();
+ len = (int) obj->lenstr();
+ }
+};
+
+struct SkDecodedText {
+ uint16_t* text;
+ int len;
+public:
+ unsigned int operator[](int i) const { return text[i]; }
+ int size() const { return len; }
+};
+
+struct SkUnicodeText {
+ uint16_t* text;
+ int len;
+
+public:
+ unsigned int operator[](int i) const { return text[i]; }
+ int size() const { return len; }
+};
+
+class SkPdfEncoding {
+public:
+ virtual ~SkPdfEncoding() {}
+ virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const = 0;
+ static SkPdfEncoding* fromName(const char* name);
+};
+
+SkTDict<SkPdfEncoding*>& getStandardEncodings();
+
+class SkPdfToUnicode {
+ // TODO(edisonn): hide public members
+public:
+ unsigned short* fCMapEncoding;
+ unsigned char* fCMapEncodingFlag;
+
+ SkPdfToUnicode(SkPdfNativeDoc* parsed, SkPdfStream* stream);
+};
+
+
+class SkPdfIdentityHEncoding : public SkPdfEncoding {
+public:
+ virtual ~SkPdfIdentityHEncoding() {}
+ virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
+ // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
+
+ uint16_t* text = (uint16_t*)textIn.text;
+ textOut->text = new uint16_t[textIn.len / 2];
+ textOut->len = textIn.len / 2;
+
+ for (int i = 0; i < textOut->len; i++) {
+ textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
+ }
+
+ return true;
+ }
+
+ static SkPdfIdentityHEncoding* instance() {
+ static SkPdfIdentityHEncoding* inst = new SkPdfIdentityHEncoding();
+ return inst;
+ }
+};
+
+// TODO(edisonn): using this one when no encoding is specified
+class SkPdfDefaultEncoding : public SkPdfEncoding {
+public:
+ virtual ~SkPdfDefaultEncoding() {}
+ virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
+ // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
+
+ unsigned char* text = (unsigned char*)textIn.text;
+ textOut->text = new uint16_t[textIn.len];
+ textOut->len = textIn.len;
+
+ for (int i = 0; i < textOut->len; i++) {
+ textOut->text[i] = text[i];
+ }
+
+ return true;
+ }
+
+ static SkPdfDefaultEncoding* instance() {
+ static SkPdfDefaultEncoding* inst = new SkPdfDefaultEncoding();
+ return inst;
+ }
+};
+
+class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding {
+public:
+ virtual ~SkPdfCIDToGIDMapIdentityEncoding() {}
+ virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const {
+ // TODO(edisonn): SkASSERT(textIn.len % 2 == 0); or report error?
+
+ uint16_t* text = (uint16_t*)textIn.text;
+ textOut->text = new uint16_t[textIn.len / 2];
+ textOut->len = textIn.len / 2;
+
+ for (int i = 0; i < textOut->len; i++) {
+ textOut->text[i] = ((text[i] << 8) & 0xff00) | ((text[i] >> 8) & 0x00ff);
+ }
+
+ return true;
+ }
+
+ static SkPdfCIDToGIDMapIdentityEncoding* instance() {
+ static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIdentityEncoding();
+ return inst;
+ }
+};
+
+class SkPdfFont {
+public:
+ SkPdfFont* fBaseFont;
+ SkPdfEncoding* fEncoding;
+ SkPdfToUnicode* fToUnicode;
+
+
+public:
+ SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfDefaultEncoding::instance()), fToUnicode(NULL) {}
+
+ virtual ~SkPdfFont() {
+ // TODO(edisonn): NYI (will leak for now)
+ }
+
+ const SkPdfEncoding* encoding() const {return fEncoding;}
+
+ void drawText(const SkDecodedText& text, SkPaint* paint, SkPdfContext* pdfContext,
+ SkCanvas* canvas) {
+ for (int i = 0 ; i < text.size(); i++) {
+ canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
+#ifdef PDF_TRACE
+ SkPoint point = SkPoint::Make(SkDoubleToScalar(0), SkDoubleToScalar(0));
+ pdfContext->fGraphicsState.fMatrixTm.mapPoints(&point, 1);
+ printf("DrawText at (%f, %f)\n", SkScalarToDouble(point.x()),
+ SkScalarToDouble(point.y()));
+#endif // PDF_TRACE
+
+#ifdef PDF_TRACE_DRAWTEXT
+ SkPaint col;
+ col.setColor(SK_ColorMAGENTA);
+ SkRect rect = SkRect::MakeXYWH(SkDoubleToScalar(0.0),
+ SkDoubleToScalar(0.0),
+ SkDoubleToScalar(10.0),
+ SkDoubleToScalar(10.0));
+ canvas->save();
+ canvas->setMatrix(pdfContext->fGraphicsState.fMatrixTm);
+ canvas->drawRect(rect, col);
+ canvas->restore();
+#endif
+ double width = drawOneChar(text[i], paint, pdfContext, canvas);
+ pdfContext->fGraphicsState.fMatrixTm.preTranslate(SkDoubleToScalar(width),
+ SkDoubleToScalar(0.0));
+ }
+ }
+
+ void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const {
+ if (fToUnicode) {
+ textOut->text = new uint16_t[textIn.len];
+ textOut->len = textIn.len;
+ for (int i = 0; i < textIn.len; i++) {
+ textOut->text[i] = fToUnicode->fCMapEncoding[textIn.text[i]];
+ }
+ } else {
+ textOut->text = textIn.text;
+ textOut->len = textIn.len;
+ }
+ };
+
+ inline unsigned int ToUnicode(unsigned int ch) const {
+ if (fToUnicode && fToUnicode->fCMapEncoding) {
+ return fToUnicode->fCMapEncoding[ch];
+ } else {
+ return ch;
+ }
+ };
+
+ static SkPdfFont* fontFromPdfDictionary(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
+ static SkPdfFont* Default() {return fontFromName(NULL, NULL, "TimesNewRoman");}
+
+ static SkPdfType0Font* fontFromType0FontDictionary(SkPdfNativeDoc* doc,
+ SkPdfType0FontDictionary* dict);
+ static SkPdfType1Font* fontFromType1FontDictionary(SkPdfNativeDoc* doc,
+ SkPdfType1FontDictionary* dict);
+ static SkPdfType3Font* fontFromType3FontDictionary(SkPdfNativeDoc* doc,
+ SkPdfType3FontDictionary* dict);
+ static SkPdfTrueTypeFont* fontFromTrueTypeFontDictionary(SkPdfNativeDoc* doc,
+ SkPdfTrueTypeFontDictionary* dict);
+ static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary(
+ SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict);
+
+ static SkPdfFont* fontFromFontDescriptor(SkPdfNativeDoc* doc,
+ SkPdfFontDescriptorDictionary* fd,
+ bool loadFromName = true);
+
+public:
+ virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
+ SkCanvas* canvas) = 0;
+ virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0;
+
+private:
+ static SkPdfFont* fontFromPdfDictionaryOnce(SkPdfNativeDoc* doc, SkPdfFontDictionary* dict);
+};
+
+class SkPdfStandardFont : public SkPdfFont {
+ SkTypeface* fTypeface;
+
+public:
+ SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {}
+
+public:
+ virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
+ SkCanvas* canvas) {
+ paint->setTypeface(fTypeface);
+ paint->setTextEncoding(SkPaint::kUTF8_TextEncoding);
+
+ unsigned long ch4 = ch;
+ char utf8[10];
+ size_t len = SkUTF8_FromUnichar((SkUnichar) ch4, utf8);
+
+ canvas->drawText(utf8, len, SkDoubleToScalar(0), SkDoubleToScalar(0), *paint);
+
+ SkScalar textWidth = paint->measureText(utf8, len);
+ return SkScalarToDouble(textWidth);
+ }
+
+ virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
+};
+
+class SkPdfType0Font : public SkPdfFont {
+public:
+ SkPdfType0Font(SkPdfNativeDoc* doc, SkPdfType0FontDictionary* dict);
+
+public:
+
+ virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
+ SkCanvas* canvas) {
+ return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
+ }
+
+ virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
+ }
+};
+
+class SkPdfType1Font : public SkPdfFont {
+public:
+ SkPdfType1Font(SkPdfNativeDoc* doc, SkPdfType1FontDictionary* dict) {
+ if (dict->has_FontDescriptor()) {
+ fBaseFont = SkPdfFont::fontFromFontDescriptor(doc, dict->FontDescriptor(doc));
+ } else {
+ fBaseFont = fontFromName(doc, dict, dict->BaseFont(doc).c_str());
+ }
+
+ if (dict->isEncodingAName(doc)) {
+ fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(doc).c_str());
+ } else if (dict->isEncodingADictionary(doc)) {
+ //SkPdfDictionary* dictEnc = dict->getEncodingAsDictionary(doc);
+ }
+ dict->FontDescriptor(doc);
+ }
+
+public:
+ virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
+ SkCanvas* canvas) {
+ return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
+ }
+
+ virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {
+
+ }
+};
+
+class SkPdfTrueTypeFont : public SkPdfType1Font {
+public:
+ SkPdfTrueTypeFont(SkPdfNativeDoc* doc, SkPdfTrueTypeFontDictionary* dict)
+ : SkPdfType1Font(doc, dict) {}
+};
+
+class SkPdfMultiMasterFont : public SkPdfType1Font {
+public:
+ SkPdfMultiMasterFont(SkPdfNativeDoc* doc, SkPdfMultiMasterFontDictionary* dict)
+ : SkPdfType1Font(doc, dict) {}
+};
+/*
+class CIDToGIDMap {
+ virtual unsigned int map(unsigned int cid) = 0;
+ static CIDToGIDMap* fromName(const char* name);
+};
+
+class CIDToGIDMap_Identity {
+ virtual unsigned int map(unsigned int cid) { return cid; }
+
+ static CIDToGIDMap_Identity* instance() {
+ static CIDToGIDMap_Identity* inst = new CIDToGIDMap_Identity();
+ return inst;
+ }
+};
+
+CIDToGIDMap* CIDToGIDMap::fromName(const char* name) {
+ // The only one supported right now is Identity
+ if (strcmp(name, "Identity") == 0) {
+ return CIDToGIDMap_Identity::instance();
+ }
+
+#ifdef PDF_TRACE
+ // TODO(edisonn): warning/report
+ printf("Unknown CIDToGIDMap: %s\n", name);
+#endif
+ return NULL;
+}
+CIDToGIDMap* fCidToGid;
+*/
+
+class SkPdfType3Font : public SkPdfFont {
+ struct Type3FontChar {
+ SkPdfNativeObject* fObj;
+ double fWidth;
+ };
+
+ SkPdfDictionary* fCharProcs;
+ SkPdfEncodingDictionary* fEncodingDict;
+ unsigned int fFirstChar;
+ unsigned int fLastChar;
+
+ SkRect fFontBBox;
+ SkMatrix fFonMatrix;
+
+ Type3FontChar* fChars;
+
+public:
+ SkPdfType3Font(SkPdfNativeDoc* parsed, SkPdfType3FontDictionary* dict) {
+ fBaseFont = fontFromName(parsed, dict, dict->BaseFont(parsed).c_str());
+
+ if (dict->has_Encoding()) {
+ if (dict->isEncodingAName(parsed)) {
+ fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName(parsed).c_str());
+ } else if (dict->isEncodingAEncodingdictionary(parsed)) {
+ // No encoding.
+ fEncoding = SkPdfDefaultEncoding::instance();
+ fEncodingDict = dict->getEncodingAsEncodingdictionary(parsed);
+ }
+ }
+
+ // null?
+ fCharProcs = dict->CharProcs(parsed);
+
+ fToUnicode = NULL;
+ if (dict->has_ToUnicode()) {
+ fToUnicode = new SkPdfToUnicode(parsed, dict->ToUnicode(parsed));
+ }
+
+ fFirstChar = (unsigned int)dict->FirstChar(parsed);
+ fLastChar = (unsigned int)dict->LastChar(parsed);
+ fFonMatrix = dict->has_FontMatrix() ? dict->FontMatrix(parsed) : SkMatrix::I();
+
+ if (dict->has_FontBBox()) {
+ fFontBBox = dict->FontBBox(parsed);
+ }
+
+ fChars = new Type3FontChar[fLastChar - fFirstChar + 1];
+
+ memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1));
+
+ const SkPdfArray* widths = dict->Widths(parsed);
+ for (unsigned int i = 0 ; i < widths->size(); i++) {
+ if ((fFirstChar + i) >= fFirstChar && (fFirstChar + i) <= fLastChar) {
+ fChars[i].fWidth = (*widths)[i]->numberValue();
+ } else {
+ // TODO(edisonn): report pdf corruption
+ }
+ }
+
+ const SkPdfArray* diffs = fEncodingDict->Differences(parsed);
+ unsigned int j = fFirstChar;
+ for (unsigned int i = 0 ; i < diffs->size(); i++) {
+ if ((*diffs)[i]->isInteger()) {
+ j = (unsigned int)(*diffs)[i]->intValue();
+ } else if ((*diffs)[i]->isName()) {
+ if (j >= fFirstChar && j <= fLastChar) {
+ fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]);
+ } else {
+ // TODO(edisonn): report pdf corruption
+ }
+ j++;
+ } else {
+ // TODO(edisonn): report bad pdf
+ }
+ }
+ }
+
+public:
+ virtual double drawOneChar(unsigned int ch, SkPaint* paint, SkPdfContext* pdfContext,
+ SkCanvas* canvas) {
+ if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) {
+ return fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas);
+ }
+
+#ifdef PDF_TRACE
+ printf("Type 3 char to unicode: %c\n", ToUnicode(ch));
+ if (ToUnicode(ch) == 'A') {
+ printf("break;\n");
+ }
+#endif
+
+ // TODO(edisonn): is it better to resolve the reference at load time, or now?
+ doType3Char(pdfContext,
+ canvas,
+ pdfContext->fPdfDoc->resolveReference(fChars[ch - fFirstChar].fObj),
+ fFontBBox,
+ fFonMatrix,
+ pdfContext->fGraphicsState.fCurFontSize);
+
+ // TODO(edisonn): verify/test translate code, not tested yet
+ pdfContext->fGraphicsState.fMatrixTm.preTranslate(
+ SkDoubleToScalar(pdfContext->fGraphicsState.fCurFontSize *
+ fChars[ch - fFirstChar].fWidth),
+ SkDoubleToScalar(0.0));
+ return fChars[ch - fFirstChar].fWidth;
+ }
+
+ virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {}
+};
+
+#endif // SkPdfFont_DEFINED