Index: experimental/PdfViewer/SkPdfFont.h |
=================================================================== |
--- experimental/PdfViewer/SkPdfFont.h (revision 9735) |
+++ experimental/PdfViewer/SkPdfFont.h (working copy) |
@@ -8,7 +8,10 @@ |
#include <string> |
#include "SkUtils.h" |
+#include "SkPdfBasics.h" |
+#include "SkPdfUtils.h" |
+ |
class SkPdfType0Font; |
class SkPdfType1Font; |
class SkPdfType3Font; |
@@ -42,6 +45,9 @@ |
struct SkDecodedText { |
uint16_t* text; |
int len; |
+public: |
+ unsigned int operator[](int i) const { return text[i]; } |
+ int size() const { return len; } |
}; |
struct SkUnicodeText { |
@@ -56,8 +62,21 @@ |
class SkPdfEncoding { |
public: |
virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const = 0; |
+ static SkPdfEncoding* fromName(const char* name); |
}; |
+std::map<std::string, SkPdfEncoding*>& getStandardEncodings(); |
+ |
+class SkPdfToUnicode { |
+ // TODO(edisonn): hide public members |
+public: |
+ unsigned short* fCMapEncoding; |
+ unsigned char* fCMapEncodingFlag; |
+ |
+ SkPdfToUnicode(const SkPdfStream* stream); |
+}; |
+ |
+ |
class SkPdfIdentityHEncoding : public SkPdfEncoding { |
public: |
virtual bool decodeText(const SkUnencodedText& textIn, SkDecodedText* textOut) const { |
@@ -80,27 +99,68 @@ |
} |
}; |
+ |
+class SkPdfCIDToGIDMapIdentityEncoding : public SkPdfEncoding { |
+public: |
+ 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 SkPdfCIDToGIDMapIdentityEncoding* instance() { |
+ static SkPdfCIDToGIDMapIdentityEncoding* inst = new SkPdfCIDToGIDMapIdentityEncoding(); |
+ return inst; |
+ } |
+}; |
+ |
class SkPdfFont { |
public: |
SkPdfFont* fBaseFont; |
SkPdfEncoding* fEncoding; |
+ SkPdfToUnicode* fToUnicode; |
+ |
public: |
- SkPdfFont() : fBaseFont(NULL), fEncoding(SkPdfIdentityHEncoding::instance()) {} |
+ SkPdfFont() : fBaseFont(NULL), fEncoding(NULL), fToUnicode(NULL) {} |
const SkPdfEncoding* encoding() const {return fEncoding;} |
- void drawText(const SkUnicodeText& text, SkPaint* paint, SkCanvas* canvas, SkMatrix* matrix) { |
+ void drawText(const SkDecodedText& text, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas, SkMatrix* matrix) { |
for (int i = 0 ; i < text.size(); i++) { |
- drawOneChar(text[i], paint, canvas, matrix); |
+ drawOneChar(text[i], paint, pdfContext, canvas, matrix); |
} |
} |
- virtual void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const { |
- textOut->text = textIn.text; |
- textOut->len = textIn.len; |
+ 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) { |
+ return fToUnicode->fCMapEncoding[ch]; |
+ } else { |
+ return ch; |
+ } |
+ }; |
+ |
static SkPdfFont* fontFromPdfDictionary(SkPdfFontDictionary* dict); |
static SkPdfFont* Default() {return SkPdfFontFromName(NULL, "TimesNewRoman");} |
@@ -112,7 +172,7 @@ |
static SkPdfMultiMasterFont* fontFromMultiMasterFontDictionary(SkPdfMultiMasterFontDictionary* dict); |
public: |
- virtual void drawOneChar(unsigned int ch, SkPaint* paint, SkCanvas* canvas, SkMatrix* matrix) = 0; |
+ virtual void drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas, SkMatrix* matrix) = 0; |
virtual void afterChar(SkPaint* paint, SkMatrix* matrix) = 0; |
virtual void afterWord(SkPaint* paint, SkMatrix* matrix) = 0; |
}; |
@@ -124,7 +184,7 @@ |
SkPdfStandardFont(SkTypeface* typeface) : fTypeface(typeface) {} |
public: |
- virtual void drawOneChar(unsigned int ch, SkPaint* paint, SkCanvas* canvas, SkMatrix* matrix) { |
+ virtual void drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas, SkMatrix* matrix) { |
paint->setTypeface(fTypeface); |
paint->setTextEncoding(SkPaint::kUTF8_TextEncoding); |
@@ -142,24 +202,14 @@ |
virtual void afterWord(SkPaint* paint, SkMatrix* matrix) {} |
}; |
- |
class SkPdfType0Font : public SkPdfFont { |
- unsigned short* fCMapEncoding; |
- unsigned char* fCMapEncodingFlag; |
public: |
SkPdfType0Font(SkPdfType0FontDictionary* dict); |
public: |
- virtual void ToUnicode(const SkDecodedText& textIn, SkUnicodeText* textOut) const { |
- textOut->text = new uint16_t[textIn.len]; |
- textOut->len = textIn.len; |
- for (int i = 0; i < textIn.len; i++) { |
- textOut->text[i] = fCMapEncoding[textIn.text[i]]; |
- } |
- }; |
- virtual void drawOneChar(unsigned int ch, SkPaint* paint, SkCanvas* canvas, SkMatrix* matrix) { |
- fBaseFont->drawOneChar(ch, paint, canvas, matrix); |
+ virtual void drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas, SkMatrix* matrix) { |
+ fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas, matrix); |
} |
virtual void afterChar(SkPaint* paint, SkMatrix* matrix) { |
@@ -167,7 +217,6 @@ |
} |
virtual void afterWord(SkPaint* paint, SkMatrix* matrix) { |
- |
} |
}; |
@@ -178,7 +227,7 @@ |
} |
public: |
- virtual void drawOneChar(unsigned int ch, SkPaint* paint, SkCanvas* canvas, SkMatrix* matrix) { |
+ virtual void drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas, SkMatrix* matrix) { |
} |
@@ -200,7 +249,7 @@ |
public: |
- virtual void drawOneChar(unsigned int ch, SkPaint* paint, SkCanvas* canvas, SkMatrix* matrix) { |
+ virtual void drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas, SkMatrix* matrix) { |
} |
@@ -221,7 +270,7 @@ |
} |
public: |
- virtual void drawOneChar(unsigned int ch, SkPaint* paint, SkCanvas* canvas, SkMatrix* matrix) { |
+ virtual void drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas, SkMatrix* matrix) { |
} |
@@ -241,7 +290,7 @@ |
} |
public: |
- virtual void drawOneChar(unsigned int ch, SkPaint* paint, SkCanvas* canvas, SkMatrix* matrix) { |
+ virtual void drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas, SkMatrix* matrix) { |
} |
@@ -253,20 +302,130 @@ |
} |
}; |
+/* |
+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 { |
+ SkPdfObject* fObj; |
+ double fWidth; |
+ }; |
+ |
+ SkPdfDictionary* fCharProcs; |
+ SkPdfEncodingDictionary* fEncodingDict; |
+ unsigned int fFirstChar; |
+ unsigned int fLastChar; |
+ |
+ SkRect fFontBBox; |
+ SkMatrix fFonMatrix; |
+ |
+ Type3FontChar* fChars; |
+ |
public: |
SkPdfType3Font(SkPdfType3FontDictionary* dict) { |
fBaseFont = SkPdfFontFromName(dict, dict->BaseFont().c_str()); |
+ |
+ if (dict->has_Encoding()) { |
+ if (dict->isEncodingAName()) { |
+ fEncoding = SkPdfEncoding::fromName(dict->getEncodingAsName().c_str()); |
+ } else if (dict->isEncodingAEncodingdictionary()) { |
+ // technically, there is no encoding. |
+ fEncoding = SkPdfCIDToGIDMapIdentityEncoding::instance(); |
+ fEncodingDict = dict->getEncodingAsEncodingdictionary(); |
+ } |
+ } |
+ |
+ // null? |
+ fCharProcs = dict->CharProcs(); |
+ |
+ fToUnicode = NULL; |
+ if (dict->has_ToUnicode()) { |
+ fToUnicode = new SkPdfToUnicode(dict->ToUnicode()); |
+ } |
+ |
+ fFirstChar = dict->FirstChar(); |
+ fLastChar = dict->LastChar(); |
+ fFonMatrix = dict->has_FontMatrix() ? *dict->FontMatrix() : SkMatrix::I(); |
+ |
+ if (dict->FontBBox()) { |
+ fFontBBox = *dict->FontBBox(); |
+ } |
+ |
+ fChars = new Type3FontChar[fLastChar - fFirstChar + 1]; |
+ |
+ memset(fChars, 0, sizeof(fChars[0]) * (fLastChar - fFirstChar + 1)); |
+ |
+ |
+ SkPdfArray* widths = dict->Widths(); |
+ for (int i = 0 ; i < widths->size(); i++) { |
+ if ((fFirstChar + i) < fFirstChar || (fFirstChar + i) > fLastChar) { |
+ printf("break; error 1\n"); |
+ } |
+ fChars[i].fWidth = (*widths)[i]->asNumber()->value(); |
+ } |
+ |
+ SkPdfArray* diffs = fEncodingDict->Differences(); |
+ int j = fFirstChar; |
+ for (int i = 0 ; i < diffs->size(); i++) { |
+ if ((*diffs)[i]->asInteger()) { |
+ j = (*diffs)[i]->asInteger()->value(); |
+ } else if ((*diffs)[i]->asName()) { |
+ if (j < fFirstChar || j > fLastChar) { |
+ printf("break; error 2\n"); |
+ } |
+ fChars[j - fFirstChar].fObj = fCharProcs->get((*diffs)[i]->asName()->value().c_str()); |
+ j++; |
+ } else { |
+ // err |
+ } |
+ } |
} |
public: |
- virtual void drawOneChar(unsigned int ch, SkPaint* paint, SkCanvas* canvas, SkMatrix* matrix) { |
+ virtual void drawOneChar(unsigned int ch, SkPaint* paint, PdfContext* pdfContext, SkCanvas* canvas, SkMatrix* matrix) { |
+ if (ch < fFirstChar || ch > fLastChar || !fChars[ch - fFirstChar].fObj) { |
+ fBaseFont->drawOneChar(ToUnicode(ch), paint, pdfContext, canvas, matrix); |
+ return; |
+ } |
+#ifdef PDF_TRACE |
+ printf("Type 3 char to unicode: %c\n", ToUnicode(ch)); |
+ if (ToUnicode(ch) == 'A') { |
+ printf("break;\n"); |
+ } |
+#endif |
+ |
+ doType3Char(pdfContext, canvas, fChars[ch - fFirstChar].fObj, fFontBBox, fFonMatrix, pdfContext->fGraphicsState.fCurFontSize); |
} |
virtual void afterChar(SkPaint* paint, SkMatrix* matrix) { |
- |
} |
virtual void afterWord(SkPaint* paint, SkMatrix* matrix) { |