Index: experimental/PdfViewer/SkPdfRenderer.cpp |
=================================================================== |
--- experimental/PdfViewer/SkPdfRenderer.cpp (revision 10235) |
+++ experimental/PdfViewer/SkPdfRenderer.cpp (working copy) |
@@ -16,11 +16,10 @@ |
#include "SkStream.h" |
#include "SkTypeface.h" |
#include "SkTArray.h" |
+#include "SkTDict.h" |
#include "SkPdfBasics.h" |
#include "SkPdfNativeTokenizer.h" |
- |
-#include <iostream> |
#include <cstdio> |
#include <stack> |
#include <set> |
@@ -78,8 +77,19 @@ |
using namespace std; |
+NotOwnedString strings_DeviceRGB; |
+NotOwnedString strings_DeviceCMYK; |
+class StringsInit { |
+public: |
+ StringsInit() { |
+ NotOwnedString::init(&strings_DeviceRGB, "DeviceRGB"); |
+ NotOwnedString::init(&strings_DeviceCMYK, "DeviceCMYK"); |
+ } |
+}; |
+StringsInit gStringsInit; |
+ |
// TODO(edisonn): Document PdfTokenLooper and subclasses. |
class PdfTokenLooper { |
protected: |
@@ -150,16 +160,16 @@ |
} |
// TODO(edisonn): synonyms? DeviceRGB and RGB ... |
-static int GetColorSpaceComponents(const std::string& colorSpace) { |
- if (colorSpace == "DeviceCMYK") { |
+static int GetColorSpaceComponents(NotOwnedString& colorSpace) { |
+ if (colorSpace.equals("DeviceCMYK")) { |
return 4; |
- } else if (colorSpace == "DeviceGray" || |
- colorSpace == "CalGray" || |
- colorSpace == "Indexed") { |
+ } else if (colorSpace.equals("DeviceGray") || |
+ colorSpace.equals("CalGray") || |
+ colorSpace.equals("Indexed")) { |
return 1; |
- } else if (colorSpace == "DeviceRGB" || |
- colorSpace == "CalRGB" || |
- colorSpace == "Lab") { |
+ } else if (colorSpace.equals("DeviceRGB") || |
+ colorSpace.equals("CalRGB") || |
+ colorSpace.equals("Lab")) { |
return 3; |
} else { |
return 0; |
@@ -317,10 +327,16 @@ |
typedef PdfResult (*PdfOperatorRenderer)(PdfContext*, SkCanvas*, PdfTokenLooper**); |
-map<std::string, PdfOperatorRenderer> gPdfOps; |
+SkTDict<PdfOperatorRenderer> gPdfOps(100); |
-map<std::string, int> gRenderStats[kCount_PdfResult]; |
+template <typename T> class SkTDictWithDefaultConstructor : public SkTDict<T> { |
+public: |
+ SkTDictWithDefaultConstructor() : SkTDict<T>(10) {} |
+}; |
+ |
+SkTDictWithDefaultConstructor<int> gRenderStats[kCount_PdfResult]; |
+ |
const char* gRenderStatsNames[kCount_PdfResult] = { |
"Success", |
"Partially implemented", |
@@ -419,7 +435,7 @@ |
return grayColortable; |
} |
-static SkBitmap transferImageStreamToBitmap(unsigned char* uncompressedStream, size_t uncompressedStreamLength, |
+static SkBitmap transferImageStreamToBitmap(const unsigned char* uncompressedStream, size_t uncompressedStreamLength, |
int width, int height, int bytesPerLine, |
int bpc, const std::string& colorSpace, |
bool transparencyMask) { |
@@ -508,12 +524,12 @@ |
} |
*/ |
- unsigned char* uncompressedStream = NULL; |
+ const unsigned char* uncompressedStream = NULL; |
size_t uncompressedStreamLength = 0; |
SkPdfStream* stream = (SkPdfStream*)image; |
- if (!stream || !stream->GetFilteredStreamRef(&uncompressedStream, &uncompressedStreamLength, pdfContext->fPdfDoc->allocator()) || |
+ if (!stream || !stream->GetFilteredStreamRef(&uncompressedStream, &uncompressedStreamLength) || |
uncompressedStream == NULL || uncompressedStreamLength == 0) { |
// TODO(edisonn): report warning to be used in testing. |
return SkBitmap(); |
@@ -654,7 +670,8 @@ |
SkPdfStream* stream = (SkPdfStream*)skobj; |
- SkPdfNativeTokenizer* tokenizer = pdfContext->fPdfDoc->tokenizerOfStream(stream); |
+ SkPdfNativeTokenizer* tokenizer = |
+ pdfContext->fPdfDoc->tokenizerOfStream(stream, pdfContext->fTmpPageAllocator); |
if (tokenizer != NULL) { |
PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas); |
looper.loop(); |
@@ -702,7 +719,8 @@ |
SkPdfStream* stream = (SkPdfStream*)skobj; |
- SkPdfNativeTokenizer* tokenizer = pdfContext->fPdfDoc->tokenizerOfStream(stream); |
+ SkPdfNativeTokenizer* tokenizer = |
+ pdfContext->fPdfDoc->tokenizerOfStream(stream, pdfContext->fTmpPageAllocator); |
if (tokenizer != NULL) { |
PdfMainLooper looper(NULL, tokenizer, pdfContext, canvas); |
looper.loop(); |
@@ -1151,10 +1169,10 @@ |
//size; they must be specified explicitly using Tf before any text is shown. |
static PdfResult PdfOp_Tf(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) { |
pdfContext->fGraphicsState.fCurFontSize = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop(); |
- const char* fontName = pdfContext->fObjectStack.top()->nameValue(); pdfContext->fObjectStack.pop(); |
+ SkPdfObject* fontName = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop(); |
#ifdef PDF_TRACE |
- printf("font name: %s\n", fontName); |
+ printf("font name: %s\n", fontName->nameValue2().c_str()); |
#endif |
if (pdfContext->fGraphicsState.fResources->Font(pdfContext->fPdfDoc)) { |
@@ -1263,7 +1281,7 @@ |
} |
static PdfResult PdfOp_CS_cs(PdfContext* pdfContext, SkCanvas* canvas, SkPdfColorOperator* colorOperator) { |
- colorOperator->fColorSpace = pdfContext->fObjectStack.top()->nameValue(); pdfContext->fObjectStack.pop(); |
+ colorOperator->fColorSpace = pdfContext->fObjectStack.top()->strRef(); pdfContext->fObjectStack.pop(); |
return kOK_PdfResult; |
} |
@@ -1282,12 +1300,12 @@ |
int n = GetColorSpaceComponents(colorOperator->fColorSpace); |
bool doubles = true; |
- if (strcmp(colorOperator->fColorSpace, "Indexed") == 0) { |
+ if (colorOperator->fColorSpace.equals("Indexed")) { |
doubles = false; |
} |
#ifdef PDF_TRACE |
- printf("color space = %s, N = %i\n", colorOperator->fColorSpace, n); |
+ printf("color space = %s, N = %i\n", colorOperator->fColorSpace.fBuffer, n); |
#endif |
for (int i = n - 1; i >= 0 ; i--) { |
@@ -1301,7 +1319,7 @@ |
// TODO(edisonn): Now, set that color. Only DeviceRGB supported. |
// TODO(edisonn): do possible field values to enum at parsing time! |
// TODO(edisonn): support also abreviations /DeviceRGB == /RGB |
- if (strcmp(colorOperator->fColorSpace, "DeviceRGB") == 0 || strcmp(colorOperator->fColorSpace, "RGB") == 0) { |
+ if (colorOperator->fColorSpace.equals("DeviceRGB") || colorOperator->fColorSpace.equals("RGB")) { |
colorOperator->setRGBColor(SkColorSetRGB(255*c[0], 255*c[1], 255*c[2])); |
} |
return kPartial_PdfResult; |
@@ -1354,7 +1372,7 @@ |
double g = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop(); |
double r = pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop(); |
- colorOperator->fColorSpace = "DeviceRGB"; |
+ colorOperator->fColorSpace = strings_DeviceRGB; |
colorOperator->setRGBColor(SkColorSetRGB(255*r, 255*g, 255*b)); |
return kOK_PdfResult; |
} |
@@ -1374,7 +1392,7 @@ |
/*double m = */pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop(); |
/*double c = */pdfContext->fObjectStack.top()->numberValue(); pdfContext->fObjectStack.pop(); |
- colorOperator->fColorSpace = "DeviceCMYK"; |
+ colorOperator->fColorSpace = strings_DeviceCMYK; |
// TODO(edisonn): Set color. |
return kNYI_PdfResult; |
} |
@@ -1504,7 +1522,7 @@ |
//dictName gs (PDF 1.2) Set the specified parameters in the graphics state. dictName is |
//the name of a graphics state parameter dictionary in the ExtGState subdictionary of the current resource dictionary (see the next section). |
static PdfResult PdfOp_gs(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) { |
- const char* name = pdfContext->fObjectStack.top()->nameValue(); pdfContext->fObjectStack.pop(); |
+ SkPdfObject* name = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop(); |
#ifdef PDF_TRACE |
std::string str; |
@@ -1622,7 +1640,7 @@ |
//name Do |
static PdfResult PdfOp_Do(PdfContext* pdfContext, SkCanvas* canvas, PdfTokenLooper** looper) { |
- const char* name = pdfContext->fObjectStack.top()->nameValue(); pdfContext->fObjectStack.pop(); |
+ SkPdfObject* name = pdfContext->fObjectStack.top(); pdfContext->fObjectStack.pop(); |
SkPdfDictionary* xObject = pdfContext->fGraphicsState.fResources->XObject(pdfContext->fPdfDoc); |
@@ -1693,94 +1711,94 @@ |
return; |
} |
- gPdfOps["q"] = PdfOp_q; |
- gPdfOps["Q"] = PdfOp_Q; |
- gPdfOps["cm"] = PdfOp_cm; |
+ gPdfOps.set("q", PdfOp_q); |
+ gPdfOps.set("Q", PdfOp_Q); |
+ gPdfOps.set("cm", PdfOp_cm); |
- gPdfOps["TD"] = PdfOp_TD; |
- gPdfOps["Td"] = PdfOp_Td; |
- gPdfOps["Tm"] = PdfOp_Tm; |
- gPdfOps["T*"] = PdfOp_T_star; |
+ gPdfOps.set("TD", PdfOp_TD); |
+ gPdfOps.set("Td", PdfOp_Td); |
+ gPdfOps.set("Tm", PdfOp_Tm); |
+ gPdfOps.set("T*", PdfOp_T_star); |
- gPdfOps["m"] = PdfOp_m; |
- gPdfOps["l"] = PdfOp_l; |
- gPdfOps["c"] = PdfOp_c; |
- gPdfOps["v"] = PdfOp_v; |
- gPdfOps["y"] = PdfOp_y; |
- gPdfOps["h"] = PdfOp_h; |
- gPdfOps["re"] = PdfOp_re; |
+ gPdfOps.set("m", PdfOp_m); |
+ gPdfOps.set("l", PdfOp_l); |
+ gPdfOps.set("c", PdfOp_c); |
+ gPdfOps.set("v", PdfOp_v); |
+ gPdfOps.set("y", PdfOp_y); |
+ gPdfOps.set("h", PdfOp_h); |
+ gPdfOps.set("re", PdfOp_re); |
- gPdfOps["S"] = PdfOp_S; |
- gPdfOps["s"] = PdfOp_s; |
- gPdfOps["f"] = PdfOp_f; |
- gPdfOps["F"] = PdfOp_F; |
- gPdfOps["f*"] = PdfOp_f_star; |
- gPdfOps["B"] = PdfOp_B; |
- gPdfOps["B*"] = PdfOp_B_star; |
- gPdfOps["b"] = PdfOp_b; |
- gPdfOps["b*"] = PdfOp_b_star; |
- gPdfOps["n"] = PdfOp_n; |
+ gPdfOps.set("S", PdfOp_S); |
+ gPdfOps.set("s", PdfOp_s); |
+ gPdfOps.set("f", PdfOp_f); |
+ gPdfOps.set("F", PdfOp_F); |
+ gPdfOps.set("f*", PdfOp_f_star); |
+ gPdfOps.set("B", PdfOp_B); |
+ gPdfOps.set("B*", PdfOp_B_star); |
+ gPdfOps.set("b", PdfOp_b); |
+ gPdfOps.set("b*", PdfOp_b_star); |
+ gPdfOps.set("n", PdfOp_n); |
- gPdfOps["BT"] = PdfOp_BT; |
- gPdfOps["ET"] = PdfOp_ET; |
+ gPdfOps.set("BT", PdfOp_BT); |
+ gPdfOps.set("ET", PdfOp_ET); |
- gPdfOps["Tj"] = PdfOp_Tj; |
- gPdfOps["'"] = PdfOp_quote; |
- gPdfOps["\""] = PdfOp_doublequote; |
- gPdfOps["TJ"] = PdfOp_TJ; |
+ gPdfOps.set("Tj", PdfOp_Tj); |
+ gPdfOps.set("'", PdfOp_quote); |
+ gPdfOps.set("\"", PdfOp_doublequote); |
+ gPdfOps.set("TJ", PdfOp_TJ); |
- gPdfOps["CS"] = PdfOp_CS; |
- gPdfOps["cs"] = PdfOp_cs; |
- gPdfOps["SC"] = PdfOp_SC; |
- gPdfOps["SCN"] = PdfOp_SCN; |
- gPdfOps["sc"] = PdfOp_sc; |
- gPdfOps["scn"] = PdfOp_scn; |
- gPdfOps["G"] = PdfOp_G; |
- gPdfOps["g"] = PdfOp_g; |
- gPdfOps["RG"] = PdfOp_RG; |
- gPdfOps["rg"] = PdfOp_rg; |
- gPdfOps["K"] = PdfOp_K; |
- gPdfOps["k"] = PdfOp_k; |
+ gPdfOps.set("CS", PdfOp_CS); |
+ gPdfOps.set("cs", PdfOp_cs); |
+ gPdfOps.set("SC", PdfOp_SC); |
+ gPdfOps.set("SCN", PdfOp_SCN); |
+ gPdfOps.set("sc", PdfOp_sc); |
+ gPdfOps.set("scn", PdfOp_scn); |
+ gPdfOps.set("G", PdfOp_G); |
+ gPdfOps.set("g", PdfOp_g); |
+ gPdfOps.set("RG", PdfOp_RG); |
+ gPdfOps.set("rg", PdfOp_rg); |
+ gPdfOps.set("K", PdfOp_K); |
+ gPdfOps.set("k", PdfOp_k); |
- gPdfOps["W"] = PdfOp_W; |
- gPdfOps["W*"] = PdfOp_W_star; |
+ gPdfOps.set("W", PdfOp_W); |
+ gPdfOps.set("W*", PdfOp_W_star); |
- gPdfOps["BX"] = PdfOp_BX; |
- gPdfOps["EX"] = PdfOp_EX; |
+ gPdfOps.set("BX", PdfOp_BX); |
+ gPdfOps.set("EX", PdfOp_EX); |
- gPdfOps["BI"] = PdfOp_BI; |
- gPdfOps["ID"] = PdfOp_ID; |
- gPdfOps["EI"] = PdfOp_EI; |
+ gPdfOps.set("BI", PdfOp_BI); |
+ gPdfOps.set("ID", PdfOp_ID); |
+ gPdfOps.set("EI", PdfOp_EI); |
- gPdfOps["w"] = PdfOp_w; |
- gPdfOps["J"] = PdfOp_J; |
- gPdfOps["j"] = PdfOp_j; |
- gPdfOps["M"] = PdfOp_M; |
- gPdfOps["d"] = PdfOp_d; |
- gPdfOps["ri"] = PdfOp_ri; |
- gPdfOps["i"] = PdfOp_i; |
- gPdfOps["gs"] = PdfOp_gs; |
+ gPdfOps.set("w", PdfOp_w); |
+ gPdfOps.set("J", PdfOp_J); |
+ gPdfOps.set("j", PdfOp_j); |
+ gPdfOps.set("M", PdfOp_M); |
+ gPdfOps.set("d", PdfOp_d); |
+ gPdfOps.set("ri", PdfOp_ri); |
+ gPdfOps.set("i", PdfOp_i); |
+ gPdfOps.set("gs", PdfOp_gs); |
- gPdfOps["Tc"] = PdfOp_Tc; |
- gPdfOps["Tw"] = PdfOp_Tw; |
- gPdfOps["Tz"] = PdfOp_Tz; |
- gPdfOps["TL"] = PdfOp_TL; |
- gPdfOps["Tf"] = PdfOp_Tf; |
- gPdfOps["Tr"] = PdfOp_Tr; |
- gPdfOps["Ts"] = PdfOp_Ts; |
+ gPdfOps.set("Tc", PdfOp_Tc); |
+ gPdfOps.set("Tw", PdfOp_Tw); |
+ gPdfOps.set("Tz", PdfOp_Tz); |
+ gPdfOps.set("TL", PdfOp_TL); |
+ gPdfOps.set("Tf", PdfOp_Tf); |
+ gPdfOps.set("Tr", PdfOp_Tr); |
+ gPdfOps.set("Ts", PdfOp_Ts); |
- gPdfOps["d0"] = PdfOp_d0; |
- gPdfOps["d1"] = PdfOp_d1; |
+ gPdfOps.set("d0", PdfOp_d0); |
+ gPdfOps.set("d1", PdfOp_d1); |
- gPdfOps["sh"] = PdfOp_sh; |
+ gPdfOps.set("sh", PdfOp_sh); |
- gPdfOps["Do"] = PdfOp_Do; |
+ gPdfOps.set("Do", PdfOp_Do); |
- gPdfOps["MP"] = PdfOp_MP; |
- gPdfOps["DP"] = PdfOp_DP; |
- gPdfOps["BMC"] = PdfOp_BMC; |
- gPdfOps["BDC"] = PdfOp_BDC; |
- gPdfOps["EMC"] = PdfOp_EMC; |
+ gPdfOps.set("MP", PdfOp_MP); |
+ gPdfOps.set("DP", PdfOp_DP); |
+ gPdfOps.set("BMC", PdfOp_BMC); |
+ gPdfOps.set("BDC", PdfOp_BDC); |
+ gPdfOps.set("EMC", PdfOp_EMC); |
gInitialized = true; |
} |
@@ -1798,8 +1816,11 @@ |
std::map<std::string, int>::iterator iter; |
for (int i = 0 ; i < kCount_PdfResult; i++) { |
- for (iter = gRenderStats[i].begin(); iter != gRenderStats[i].end(); ++iter) { |
- printf("%s: %s -> count %i\n", gRenderStatsNames[i], iter->first.c_str(), iter->second); |
+ SkTDict<int>::Iter iter(gRenderStats[i]); |
+ const char* key; |
+ int value = 0; |
+ while ((key = iter.next(&value)) != NULL) { |
+ printf("%s: %s -> count %i\n", gRenderStatsNames[i], key, value); |
} |
} |
} |
@@ -1812,19 +1833,25 @@ |
strncpy(keyword, token.fKeyword, token.fKeywordLength); |
keyword[token.fKeywordLength] = '\0'; |
// TODO(edisonn): log trace flag (verbose, error, info, warning, ...) |
- PdfOperatorRenderer pdfOperatorRenderer = gPdfOps[keyword]; |
- if (pdfOperatorRenderer) { |
+ PdfOperatorRenderer pdfOperatorRenderer = NULL; |
+ if (gPdfOps.find(keyword, &pdfOperatorRenderer) && pdfOperatorRenderer) { |
// caller, main work is done by pdfOperatorRenderer(...) |
PdfTokenLooper* childLooper = NULL; |
- gRenderStats[pdfOperatorRenderer(fPdfContext, fCanvas, &childLooper)][keyword]++; |
+ PdfResult result = pdfOperatorRenderer(fPdfContext, fCanvas, &childLooper); |
+ int cnt = 0; |
+ gRenderStats[result].find(keyword, &cnt); |
+ gRenderStats[result].set(keyword, cnt + 1); |
+ |
if (childLooper) { |
childLooper->setUp(this); |
childLooper->loop(); |
delete childLooper; |
} |
} else { |
- gRenderStats[kUnsupported_PdfResult][keyword]++; |
+ int cnt = 0; |
+ gRenderStats[kUnsupported_PdfResult].find(keyword, &cnt); |
+ gRenderStats[kUnsupported_PdfResult].set(keyword, cnt + 1); |
} |
} |
else if (token.fType == kObject_TokenType) |
@@ -1919,9 +1946,10 @@ |
return false; |
} |
- SkPdfNativeTokenizer* tokenizer = fPdfDoc->tokenizerOfPage(page); |
+ PdfContext pdfContext(fPdfDoc); |
- PdfContext pdfContext(fPdfDoc); |
+ SkPdfNativeTokenizer* tokenizer = fPdfDoc->tokenizerOfPage(page, pdfContext.fTmpPageAllocator); |
+ |
pdfContext.fOriginalMatrix = SkMatrix::I(); |
pdfContext.fGraphicsState.fResources = fPdfDoc->pageResources(page); |