From f6dfb12544b0bdf05835eb6c0dc416a09f8595dc Mon Sep 17 00:00:00 2001 From: rylek Date: Tue, 8 Jun 2010 23:37:13 +0000 Subject: [PATCH] Basic support for fill patterns in PDF git-svn-id: svn://ultimatepp.org/upp/trunk@2467 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/PdfDraw/PdfDraw.cpp | 137 ++++++++++++++++++++++++++++++++++--- uppsrc/PdfDraw/PdfDraw.h | 10 +-- uppsrc/TCtrlLib/Help/init | 5 ++ 3 files changed, 138 insertions(+), 14 deletions(-) create mode 100644 uppsrc/TCtrlLib/Help/init diff --git a/uppsrc/PdfDraw/PdfDraw.cpp b/uppsrc/PdfDraw/PdfDraw.cpp index 9fee5b355..36d77e8a8 100644 --- a/uppsrc/PdfDraw/PdfDraw.cpp +++ b/uppsrc/PdfDraw/PdfDraw.cpp @@ -5,7 +5,7 @@ NAMESPACE_UPP #define LDUMP(x) // DUMP(x) #define LLOG(x) // LOG(x) -#define PDF_COMPRESS +//#define PDF_COMPRESS #define USE_TTF dword PdfDraw::GetInfo() const @@ -25,6 +25,7 @@ void PdfDraw::Init(int pagecx, int pagecy, int _margin) pgsz.cx = pagecx; pgsz.cy = pagecy; pgsz += margin; + StartPage(); } void PdfDraw::Clear() @@ -78,10 +79,23 @@ int PdfDraw::PutStream(const String& data, const String& keys) return offset.GetCount(); } -void PdfDraw::PutrgColor(Color rg) +void PdfDraw::PutrgColor(Color rg, uint64 pattern) { - if(IsNull(rgcolor) || rg != rgcolor) - page << PdfColor(rgcolor = rg) << " rg\n"; + if(IsNull(rgcolor) || rg != rgcolor || pattern != patternid) { + if(!pattern) { + page << PdfColor(rg) << " rg\n"; + } + else { + int f = patterns.FindAdd(pattern); + if(!patternid) + page << "/Cspat cs\n"; + page << PdfColor(rg) << + " /Pat" << (f + 1) << " scn\n"; + } + + } + rgcolor = rg; + patternid = pattern; } void PdfDraw::PutRGColor(Color RG) @@ -101,6 +115,7 @@ void PdfDraw::StartPage() { rgcolor = RGcolor = Null; fontid = -1; + patternid = 0; textht = Null; linewidth = -1; if(margin) @@ -123,6 +138,7 @@ void PdfDraw::BeginOp() void PdfDraw::EndOp() { fontid = -1; + patternid = 0; textht = Null; rgcolor = RGcolor = Null; linewidth = -1; @@ -514,8 +530,8 @@ void PdfDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count, const int *disjunct_polygon_counts, int disjunct_polygon_count_count, Color color, int width, Color outline, uint64 pattern, Color doxor) { - bool fill = !IsNull(color), stroke = !IsNull(outline) && !IsNull(width); - if(fill) PutrgColor(color); + bool fill = !IsNull(color) && ~pattern, stroke = !IsNull(outline) && !IsNull(width); + if(fill) PutrgColor(color, pattern); if(stroke) { PutRGColor(outline); PutLineWidth(width); } if(!fill && !stroke) return; const char *closeop = (fill & stroke ? "B*" : fill ? "f*" : "S"); @@ -573,7 +589,7 @@ String GetGrayPdfImage(const Image& m, const Rect& sr) String PdfDraw::Finish() { - if(!IsNull(page)) + if(page.GetLength()) PutStream(page); int pagecount = offset.GetCount(); @@ -663,6 +679,98 @@ String PdfDraw::Finish() imageobj << PutStream(data, imgobj); } + int patcsobj = -1; + int patresobj = -1; + if(!patterns.IsEmpty()) { + patcsobj = BeginObj(); + out << "[/Pattern /DeviceRGB]\n"; + EndObj(); + patresobj = BeginObj(); + out << "<< >>\n"; + EndObj(); + } + + Vector patternobj; + patternobj.SetCount(patterns.GetCount(), -1); + for(int i = 0; i < patterns.GetCount(); i++) { + uint64 pat = patterns[i]; + StringBuffer ptk; + ptk << + "/Type /Pattern\n" + "/PatternType 1\n" + "/PaintType 2\n" + "/TilingType 3\n" + "/BBox [-1 -1 9 9]\n" + "/XStep 8\n" + "/YStep 8\n" + "/Resources " << patresobj << " 0 R\n" + "/Matrix [0.75 0.0 0.0 0.75 0.0 0.0]\n" // pattern pixels -> dots + ; + StringBuffer ptd; + for(int y = 0; y < 8; y++) { + for(int x = 0; x < 8; x++) { + int b = 8 * y + x, e, lim; + if(!((pat >> b) & 1)) { + e = 0; + lim = 8 - x; + while(++e < lim && !((pat >> (b + e)) & 1)) + pat |= (uint64(1) << (b + e)); + if(e > 1) + ptd << x << ' ' << (7 - y) << ' ' << e << " 1 re f\n"; + else { + e = 0; + lim = 8 - y; + while(++e < lim && !((pat >> (b + 8 * e)) & 1)) + pat |= (uint64(1) << (b + 8 * e)); + if(e - y > 1) + ptd << x << ' ' << (7 - y - e) << " 1 " << e << " re f\n"; + else { + e = 0; + lim = 8 - max(x, y); + while(++e < lim && !((pat >> (b + 9 * e)) & 1)) + pat |= (uint64(1) << (b + 9 * e)); + if(e > 1) { + ptd + << FormatDouble(x - 0.25, 2) << " " + << FormatDouble(7.75 - y, 2) << " m\n" + << FormatDouble(x + 0.25, 2) << " " + << FormatDouble(8.25 - y, 2) << " l\n" + << FormatDouble(x + e + 0.25, 2) << " " + << FormatDouble(8.25 - y - e, 2) << " l\n" + << FormatDouble(x + e - 0.25, 2) << " " + << FormatDouble(7.75 - y - e, 2) << " l\n" + << "f\n"; + } + else { + e = 0; + lim = 8 - max(7 - x, y); + while(++e < lim && !((pat >> (b + 7 * e)) & 1)) + pat |= (uint64(1) << (b + 7 * e)); + if(e > 1) { + ptd + << FormatDouble(x + 1.25, 2) << " " + << FormatDouble(7.75 - y, 2) << " m\n" + << FormatDouble(x + 0.75, 2) << " " + << FormatDouble(8.25 - y, 2) << " l\n" + << FormatDouble(x - e + 0.75, 2) << " " + << FormatDouble(8.25 - y - e, 2) << " l\n" + << FormatDouble(x - e + 1.25, 2) << " " + << FormatDouble(7.75 - y - e, 2) << " l\n" + << "f\n"; + } + else { + ptd << x << ' ' << (7 - y) << " 1 1 re f\n"; + } + } + } + } + } + } + } + patternobj[i] = PutStream(ptd, ptk); + + } + /* Vector rgobj; Vector rgsz; @@ -858,11 +966,20 @@ String PdfDraw::Finish() EndObj(); int resources = BeginObj(); - out << "<< /Font " << fonts << " 0 R /ProcSet [ /PDF /Text /ImageB /ImageC ]"; + out << "<< /Font " << fonts << " 0 R\n" + "/ProcSet [ /PDF /Text /ImageB /ImageC ]\n"; if(imageobj.GetCount()) { - out << " /XObject << "; + out << "/XObject << "; for(int i = 0; i < imageobj.GetCount(); i++) - out << "/Image" << i + 1 << ' ' << imageobj[i] << " 0 R "; + out << "/Image" << (i + 1) << ' ' << imageobj[i] << " 0 R "; + out << ">>\n"; + } + if(!patternobj.IsEmpty()) { + out << + "/ColorSpace << /Cspat " << patcsobj << " 0 R >>\n" + "/Pattern << "; + for(int i = 0; i < patterns.GetCount(); i++) + out << "/Pat" << (i + 1) << ' ' << patternobj[i] << " 0 R "; out << ">>\n"; } out << ">>\n"; diff --git a/uppsrc/PdfDraw/PdfDraw.h b/uppsrc/PdfDraw/PdfDraw.h index 98876e751..304fad269 100644 --- a/uppsrc/PdfDraw/PdfDraw.h +++ b/uppsrc/PdfDraw/PdfDraw.h @@ -271,10 +271,11 @@ private: VectorMap > fontchars; Vector image; Vector imagerect; + Index patterns; - Vector offset; - String out; - String page; + Vector offset; + StringBuffer out; + StringBuffer page; Size pgsz; Color rgcolor; Color RGcolor; @@ -282,6 +283,7 @@ private: double textht; double linewidth; int margin; + uint64 patternid; inline double Pt(double dot) { return 0.12 * dot; } @@ -291,7 +293,7 @@ private: int PutStream(const String& data, const String& keys = Null); void PutRect(const Rect& rc); - void PutrgColor(Color rg); + void PutrgColor(Color rg, uint64 pattern = 0); void PutRGColor(Color RG); void PutFontHeight(int fi, double ht); void PutLineWidth(int lw); diff --git a/uppsrc/TCtrlLib/Help/init b/uppsrc/TCtrlLib/Help/init new file mode 100644 index 000000000..ca27f992e --- /dev/null +++ b/uppsrc/TCtrlLib/Help/init @@ -0,0 +1,5 @@ +#ifndef _TCtrlLib_Help_icpp_init_stub +#define _TCtrlLib_Help_icpp_init_stub +#include "TCtrlLib/init" +#include "RichText/init" +#endif