mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
developing new draw
git-svn-id: svn://ultimatepp.org/upp/trunk@1373 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
fa47b4615a
commit
f67d0a41eb
47 changed files with 1913 additions and 0 deletions
21
uppsrc/PdfDraw/Copying
Normal file
21
uppsrc/PdfDraw/Copying
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Copyright 1998-2008 The U++ Project. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
conditions and the following disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE U++ PROJECT ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
834
uppsrc/PdfDraw/PdfDraw.cpp
Normal file
834
uppsrc/PdfDraw/PdfDraw.cpp
Normal file
|
|
@ -0,0 +1,834 @@
|
|||
#include "PdfDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#define LDUMP(x) // DUMP(x)
|
||||
#define LLOG(x) // LOG(x)
|
||||
|
||||
#define PDF_COMPRESS
|
||||
#define USE_TTF
|
||||
|
||||
dword PdfDraw::GetInfo() const
|
||||
{
|
||||
return DOTS;
|
||||
}
|
||||
|
||||
Size PdfDraw::GetPageSize() const
|
||||
{
|
||||
return pgsz;
|
||||
}
|
||||
|
||||
void PdfDraw::Init(int pagecx, int pagecy, int _margin)
|
||||
{
|
||||
Clear();
|
||||
margin = _margin;
|
||||
pgsz.cx = pagecx;
|
||||
pgsz.cy = pagecy;
|
||||
pgsz += margin;
|
||||
}
|
||||
|
||||
void PdfDraw::Clear()
|
||||
{
|
||||
out.Clear();
|
||||
page.Clear();
|
||||
offset.Clear();
|
||||
out << "%PDF-1.3\n";
|
||||
out << "%\xf1\xf2\xf3\xf4\n\n";
|
||||
}
|
||||
|
||||
int PdfDraw::BeginObj()
|
||||
{
|
||||
offset.Add(out.GetLength());
|
||||
out << offset.GetCount() << " 0 obj\n";
|
||||
return offset.GetCount();
|
||||
}
|
||||
|
||||
void PdfDraw::EndObj()
|
||||
{
|
||||
out << "endobj\n\n";
|
||||
}
|
||||
|
||||
void PdfDraw::PutRect(const Rect& rc)
|
||||
{
|
||||
page << Pt(rc.left) << ' ' << Pt(pgsz.cy - rc.bottom) << ' '
|
||||
<< Pt(rc.Width()) << ' ' << Pt(rc.Height()) << " re\n";
|
||||
}
|
||||
|
||||
int PdfDraw::PutStream(const String& data, const String& keys)
|
||||
{
|
||||
#ifdef PDF_COMPRESS
|
||||
String c = ZCompress(data);
|
||||
if(c.GetLength() < data.GetLength()) {
|
||||
BeginObj();
|
||||
out << "<< " << keys
|
||||
<< "/Length " << c.GetLength() << " "
|
||||
<< "/Length1 " << data.GetLength() << " "
|
||||
<< "/Filter /FlateDecode "
|
||||
<< " >>\n"
|
||||
<< "stream\r\n" << c << "\r\nendstream\n";
|
||||
EndObj();
|
||||
return offset.GetCount();
|
||||
}
|
||||
#endif
|
||||
BeginObj();
|
||||
out << "<< " << keys << " /Length " << data.GetLength() <<
|
||||
" /Length1 "<< data.GetLength() << " >>\n"
|
||||
<< "stream\r\n" << data << "\r\nendstream\n";
|
||||
EndObj();
|
||||
return offset.GetCount();
|
||||
}
|
||||
|
||||
void PdfDraw::PutrgColor(Color rg)
|
||||
{
|
||||
if(IsNull(rgcolor) || rg != rgcolor)
|
||||
page << PdfColor(rgcolor = rg) << " rg\n";
|
||||
}
|
||||
|
||||
void PdfDraw::PutRGColor(Color RG)
|
||||
{
|
||||
if(IsNull(RGcolor) || RG != RGcolor)
|
||||
page << PdfColor(RGcolor = RG) << " RG\n";
|
||||
}
|
||||
|
||||
void PdfDraw::PutLineWidth(int lw)
|
||||
{
|
||||
lw = max(Nvl(lw, 0), 5);
|
||||
if(linewidth != lw)
|
||||
page << Pt(linewidth = lw) << " w\n";
|
||||
}
|
||||
|
||||
void PdfDraw::StartPage()
|
||||
{
|
||||
rgcolor = RGcolor = Null;
|
||||
fontid = -1;
|
||||
textht = Null;
|
||||
linewidth = -1;
|
||||
if(margin)
|
||||
OffsetOp(Point(margin, margin));
|
||||
}
|
||||
|
||||
void PdfDraw::EndPage()
|
||||
{
|
||||
if(margin)
|
||||
EndOp();
|
||||
PutStream(page);
|
||||
page.Clear();
|
||||
}
|
||||
|
||||
void PdfDraw::BeginOp()
|
||||
{
|
||||
page << "q\n";
|
||||
}
|
||||
|
||||
void PdfDraw::EndOp()
|
||||
{
|
||||
fontid = -1;
|
||||
textht = Null;
|
||||
rgcolor = RGcolor = Null;
|
||||
linewidth = -1;
|
||||
page << "Q\n";
|
||||
}
|
||||
|
||||
void PdfDraw::OffsetOp(Point p)
|
||||
{
|
||||
page << "q ";
|
||||
if(p.x || p.y)
|
||||
page << "1 0 0 1 " << Pt(p.x) << ' ' << Pt(-p.y) << " cm\n";
|
||||
}
|
||||
|
||||
bool PdfDraw::ClipOp(const Rect& r)
|
||||
{
|
||||
page << "q ";
|
||||
PutRect(r);
|
||||
page << "W* n\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PdfDraw::ClipoffOp(const Rect& r)
|
||||
{
|
||||
page << "q ";
|
||||
PutRect(r);
|
||||
page << "W* n\n";
|
||||
if(r.left || r.top)
|
||||
page << "1 0 0 1 " << Pt(r.left) << ' ' << Pt(-r.top) << " cm\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PdfDraw::ExcludeClipOp(const Rect& r)
|
||||
{
|
||||
return true; // TODO
|
||||
/*
|
||||
if(r.left <= actual_clip.left && r.right >= actual_clip.right) {
|
||||
if(r.top <= actual_clip.top) actual_clip.top = max(actual_clip.top, r.bottom);
|
||||
if(r.bottom >= actual_clip.bottom) actual_clip.bottom = min(actual_clip.bottom, r.top);
|
||||
}
|
||||
if(r.top <= actual_clip.top && r.bottom >= actual_clip.bottom) {
|
||||
if(r.left <= actual_clip.left) actual_clip.left = max(actual_clip.left, r.right);
|
||||
if(r.right >= actual_clip.right) actual_clip.right = min(actual_clip.right, r.left);
|
||||
}
|
||||
|
||||
PutRect(actual_clip);
|
||||
PutRect(r & actual_clip);
|
||||
page << "W* n\n";
|
||||
return !actual_clip.IsEmpty();
|
||||
*/
|
||||
}
|
||||
|
||||
bool PdfDraw::IntersectClipOp(const Rect& r)
|
||||
{
|
||||
PutRect(r);
|
||||
page << "W* n\n";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PdfDraw::IsPaintingOp(const Rect&) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
PdfDraw::CharPos PdfDraw::GetCharPos(Font fnt, wchar chr)
|
||||
{
|
||||
fnt.Underline(false);
|
||||
VectorMap<wchar, CharPos>& fc = fontchars.GetAdd(fnt);
|
||||
int q = fc.Find(chr);
|
||||
if(q >= 0)
|
||||
return fc[q];
|
||||
CharPos& p = fc.Add(chr);
|
||||
q = pdffont.FindLast(fnt);
|
||||
if(q < 0 || pdffont[q].GetCount() > 250) {
|
||||
p.fi = pdffont.GetCount();
|
||||
p.ci = 0;
|
||||
pdffont.Add(fnt).Add(chr);
|
||||
}
|
||||
else {
|
||||
p.fi = q;
|
||||
p.ci = pdffont[q].GetCount();
|
||||
pdffont[q].Add(chr);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
void PdfDraw::FlushText(int dx, int fi, int height, const String& txt)
|
||||
{
|
||||
if(fi < 0)
|
||||
return;
|
||||
if(dx)
|
||||
page << Pt(dx) << " 0 Td ";
|
||||
PutFontHeight(fi, height);
|
||||
page << "<" << txt << "> Tj\n";
|
||||
}
|
||||
|
||||
String PdfDraw::PdfColor(Color c)
|
||||
{
|
||||
return NFormat("%3nf %3nf %3nf", c.GetR() / 255.0, c.GetG() / 255.0, c.GetB() / 255.0);
|
||||
}
|
||||
|
||||
void PdfDraw::PutFontHeight(int fi, double ht)
|
||||
{
|
||||
if(fi != fontid || IsNull(textht) || ht != textht)
|
||||
page << "/F" << ((fontid = fi) + 1) << ' ' << Pt(textht = ht) << " Tf\n";
|
||||
}
|
||||
|
||||
PdfDraw::OutlineInfo PdfDraw::GetOutlineInfo(Font fnt)
|
||||
{
|
||||
fnt.Height(0);
|
||||
int q = outline_info.Find(fnt);
|
||||
if(q >= 0)
|
||||
return outline_info[q];
|
||||
OutlineInfo of;
|
||||
of.sitalic = of.ttf = false;
|
||||
|
||||
#ifdef USE_TTF
|
||||
#ifdef PLATFORM_WIN32
|
||||
ScreenDraw info;
|
||||
info.SetFont(fnt().Underline(false));
|
||||
TEXTMETRIC tm;
|
||||
GetTextMetrics(info.GetHandle(), &tm);
|
||||
if(tm.tmPitchAndFamily & TMPF_TRUETYPE) {
|
||||
of.ttf = true;
|
||||
int c = GetOutlineTextMetrics(info.GetHandle(), 0, NULL);
|
||||
if(c > 0) {
|
||||
Buffer<byte> h(c);
|
||||
OUTLINETEXTMETRIC *otm = (OUTLINETEXTMETRIC *)~h;
|
||||
GetOutlineTextMetrics(info.GetHandle(), c, otm);
|
||||
of.sitalic = otm->otmItalicAngle == 0 && fnt.IsItalic();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef PLATFORM_X11
|
||||
FontInfo fi = fnt.Info();
|
||||
String fn = fi.GetFileName();
|
||||
String ext = ToLower(GetFileExt(fn));
|
||||
if(ext == ".ttf" || ext == ".otf") {
|
||||
String data = LoadFile(fn);
|
||||
TTFReader ttf;
|
||||
if(ttf.Open(data, false, true)) {
|
||||
of.ttf = true;
|
||||
of.sitalic = ttf.post.italicAngle == 0 && fnt.IsItalic();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
outline_info.Add(fnt, of);
|
||||
|
||||
return of;
|
||||
}
|
||||
|
||||
void PdfDraw::DrawTextOp(int x, int y, int angle, const wchar *s, Font fnt,
|
||||
Color ink, int n, const int *dx)
|
||||
{
|
||||
if(!n) return;
|
||||
if(fnt.GetHeight() == 0)
|
||||
fnt.Height(100);
|
||||
FontInfo ff = fnt.Info();
|
||||
#ifdef PLATFORM_WIN32
|
||||
int fh = ff.GetHeight() - ff.GetInternal();//TODO
|
||||
#endif
|
||||
#ifdef PLATFORM_X11
|
||||
int fh = fnt.GetHeight();
|
||||
#endif
|
||||
OutlineInfo of = GetOutlineInfo(fnt);
|
||||
if(of.ttf)
|
||||
fnt.Height(0);
|
||||
String txt;
|
||||
PutrgColor(ink);
|
||||
PutRGColor(ink);
|
||||
page << "BT ";
|
||||
double sina = 0, cosa = 1;
|
||||
int posx = 0;
|
||||
if(angle || dx || (of.sitalic && !fnt.IsItalic())) {
|
||||
M22 m;
|
||||
if(of.sitalic)
|
||||
m.c = 0.165;
|
||||
if(angle) {
|
||||
Draw::SinCos(angle, sina, cosa);
|
||||
m.Mul(cosa, sina, -sina, cosa);
|
||||
}
|
||||
int fi = -1;
|
||||
bool straight = (fabs(m.a - 1) <= 1e-8 && fabs(m.b) <= 1e-8 && fabs(m.c) <= 1e-8 && fabs(m.d - 1) <= 1e-8);
|
||||
Pointf prev(0, 0);
|
||||
for(int i = 0; i < n; i++) {
|
||||
Pointf next(Pt(x + posx * cosa + fround(ff.GetAscent() * sina)),
|
||||
Pt(pgsz.cy - (y - posx * sina) - fround(ff.GetAscent() * cosa)));
|
||||
CharPos fp = GetCharPos(fnt, s[i]);
|
||||
if(fi != fp.fi) {
|
||||
fi = fp.fi;
|
||||
PutFontHeight(fi, fh);
|
||||
}
|
||||
if(straight)
|
||||
page << (next.x - prev.x) << ' ' << (next.y - prev.y) << " Td";
|
||||
else
|
||||
page << m.a << ' ' << m.b << ' ' << m.c << ' ' << m.d << ' ' << next.x << ' ' << next.y << " Tm";
|
||||
page << " <" << FormatIntHex(fp.ci, 2);
|
||||
while(i + 1 < n) {
|
||||
int cw = ff[s[i]];
|
||||
if(dx && dx[i] != cw)
|
||||
break;
|
||||
posx += cw;
|
||||
CharPos np = GetCharPos(fnt, s[i + 1]);
|
||||
if(np.fi != fp.fi)
|
||||
break;
|
||||
page << FormatIntHex(np.ci, 2);
|
||||
i++;
|
||||
}
|
||||
page << "> Tj\n";
|
||||
posx += dx ? dx[i] : ff[s[i]];
|
||||
prev = next;
|
||||
}
|
||||
}
|
||||
else {
|
||||
page << Pt(x) << " " << Pt(pgsz.cy - y - ff.GetAscent()) << " Td\n";
|
||||
int fi = -1;
|
||||
int ppos = 0;
|
||||
int np = 0;
|
||||
for(int i = 0; i < n; i++) {
|
||||
CharPos fp = GetCharPos(fnt, s[i]);
|
||||
if(fp.fi != fi) {
|
||||
FlushText(np, fi, fnt.GetHeight(), txt);
|
||||
txt.Clear();
|
||||
np = posx - ppos;
|
||||
ppos = posx;
|
||||
fi = fp.fi;
|
||||
}
|
||||
txt.Cat(Sprintf("%02.2X", fp.ci));
|
||||
posx += ff[s[i]];
|
||||
}
|
||||
FlushText(np, fi, fh, txt);
|
||||
}
|
||||
page << "ET\n";
|
||||
if(fnt.IsUnderline()) {
|
||||
int w = ff.GetAscent() / 15;
|
||||
int dy = ff.GetAscent() + max((ff.GetDescent() - w) / 2, ff.GetAscent() / 10);
|
||||
DrawLine(fround(x + sina * dy),
|
||||
fround(y + cosa * dy),
|
||||
fround(x + cosa * posx + sina * dy),
|
||||
fround(y + cosa * dy - sina * posx), w, ink);
|
||||
}
|
||||
}
|
||||
|
||||
Image RenderGlyph(int cx, int x, Font font, int chr, int py, int pcy)
|
||||
{
|
||||
ImageDraw iw(cx, pcy);
|
||||
iw.DrawRect(0, 0, cx, pcy, White);
|
||||
iw.DrawText(x, -py, WString(chr, 1), font, Black);
|
||||
return iw;
|
||||
}
|
||||
|
||||
PdfDraw::RGlyph PdfDraw::RasterGlyph(Font fnt, int chr)
|
||||
{
|
||||
RGlyph rg;
|
||||
FontInfo fi = fnt.Info();
|
||||
rg.x = 0;
|
||||
rg.sz.cx = fi[chr];
|
||||
rg.sz.cy = fi.GetHeight();
|
||||
int l = fi.GetLeftSpace(chr);
|
||||
if(l < 0) {
|
||||
rg.x = -l;
|
||||
rg.sz.cx -= l;
|
||||
}
|
||||
int r = fi.GetRightSpace(chr);
|
||||
if(r < 0)
|
||||
rg.sz.cx -= r;
|
||||
RasterFormat fmt;
|
||||
fmt.Set1mf();
|
||||
int linebytes = fmt.GetByteCount(rg.sz.cx);
|
||||
Buffer<byte> ob(linebytes);
|
||||
int y = 0;
|
||||
while(y < rg.sz.cy) {
|
||||
int ccy = min(16, rg.sz.cy - y);
|
||||
Image m = RenderGlyph(rg.sz.cx, rg.x, fnt, chr, y, ccy);
|
||||
for(int i = 0; i < m.GetHeight(); i++) {
|
||||
fmt.Write(ob, m[i], rg.sz.cx, NULL);
|
||||
rg.data.Cat((const char *)~ob, linebytes);
|
||||
}
|
||||
y += ccy;
|
||||
}
|
||||
return rg;
|
||||
}
|
||||
|
||||
void PdfDraw::DrawRectOp(int x, int y, int cx, int cy, Color color)
|
||||
{
|
||||
if(IsNull(color) || cx <= 0 || cy <= 0) return;
|
||||
PutrgColor(color);
|
||||
PutRGColor(color);
|
||||
PutRect(RectC(x, y, cx, cy));
|
||||
page << "f\n";
|
||||
}
|
||||
|
||||
void PdfDraw::DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color)
|
||||
{
|
||||
if(!IsNull(width)) {
|
||||
PutRGColor(color);
|
||||
PutLineWidth(width);
|
||||
page << " 1 J "
|
||||
<< Pt(x1) << ' ' << Pt(pgsz.cy - y1) << " m "
|
||||
<< Pt(x2) << ' ' << Pt(pgsz.cy - y2) << " l S\n";
|
||||
}
|
||||
}
|
||||
|
||||
void PdfDraw::DrawImageOp(int x, int y, int cx, int cy, const Image& _img, const Rect& src, Color c)
|
||||
{
|
||||
Image img = _img;
|
||||
if(!IsNull(c))
|
||||
img = SetColorKeepAlpha(img, c);
|
||||
image.Add(img);
|
||||
imagerect.Add(src);
|
||||
page << "q "
|
||||
<< Pt(cx) << " 0 0 " << Pt(cy) << ' '
|
||||
<< Pt(x) << ' ' << Pt(pgsz.cy - y - cy)
|
||||
<< " cm /Image" << image.GetCount() << " Do Q\n";
|
||||
}
|
||||
|
||||
void PdfDraw::DrawPolyPolylineOp(const Point *vertices, int vertex_count,
|
||||
const int *counts, int count_count,
|
||||
int width, Color color, Color doxor)
|
||||
{
|
||||
if(IsNull(color) || IsNull(width))
|
||||
return;
|
||||
PutRGColor(color);
|
||||
PutLineWidth(width);
|
||||
while(--count_count >= 0) {
|
||||
int part = *counts++;
|
||||
page << Pt(vertices->x) << ' ' << Pt(pgsz.cy - vertices->y) << " m\n";
|
||||
vertices++;
|
||||
for(; --part > 0; vertices++)
|
||||
page << Pt(vertices->x) << ' ' << Pt(pgsz.cy - vertices->y) << " l\n";
|
||||
page << "S\n";
|
||||
}
|
||||
}
|
||||
|
||||
void PdfDraw::DrawEllipseOp(const Rect& r, Color color, int pen, Color outline)
|
||||
{
|
||||
bool fill = !IsNull(color), stroke = !IsNull(outline) && !IsNull(pen);
|
||||
if(fill) PutrgColor(color);
|
||||
if(stroke) { PutRGColor(outline); PutLineWidth(pen); }
|
||||
if(!fill && !stroke)
|
||||
return;
|
||||
char closeop = (stroke && fill ? 'B' : fill ? 'f' : 'S');
|
||||
int sizelim = r.Width() | r.Height();
|
||||
int bits = 1;
|
||||
while(bits < 20 && sizelim > (1 << bits))
|
||||
bits++;
|
||||
int parts = 3 + max(((bits * (bits - 6)) >> 3) | 1, 1);
|
||||
double k = 2 * M_PI / 3 / parts;
|
||||
Pointf center(Pt((r.left + r.right) / 2.0), Pt(pgsz.cy - ((r.top + r.bottom) / 2.0)));
|
||||
Pointf size(Pt(r.Width() / 2.0), Pt(r.Height() / 2.0));
|
||||
for(int partid = 0; partid < parts; partid++) {
|
||||
double phi1 = (partid + 0) * (2 * M_PI / parts);
|
||||
double phi2 = (partid + 1) * (2 * M_PI / parts);
|
||||
double s1 = sin(phi1), c1 = cos(phi1), s2 = sin(phi2), c2 = cos(phi2);
|
||||
Pointf A = center + Pointf(c1, s1) * size;
|
||||
Pointf D = center + Pointf(c2, s2) * size;
|
||||
Pointf dA = Pointf(-s1, c1) * size;
|
||||
Pointf dD = Pointf(-s2, c2) * size;
|
||||
Pointf B = A + k * dA;
|
||||
Pointf C = D - k * dD;
|
||||
if(!partid)
|
||||
page << FormatDoubleFix(A.x, 2) << ' ' << FormatDoubleFix(A.y, 2) << " m\n";
|
||||
page << FormatDoubleFix(B.x, 2) << ' ' << FormatDoubleFix(B.y, 2) << ' '
|
||||
<< FormatDoubleFix(C.x, 2) << ' ' << FormatDoubleFix(C.y, 2) << ' '
|
||||
<< FormatDoubleFix(D.x, 2) << ' ' << FormatDoubleFix(D.y, 2) << " c\n";
|
||||
}
|
||||
page << closeop << '\n';
|
||||
}
|
||||
|
||||
void PdfDraw::DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color)
|
||||
{
|
||||
//TODO!!
|
||||
NEVER();
|
||||
}
|
||||
|
||||
void PdfDraw::DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
|
||||
const int *subpolygon_counts, int subpolygon_count_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);
|
||||
if(stroke) { PutRGColor(outline); PutLineWidth(width); }
|
||||
if(!fill && !stroke) return;
|
||||
const char *closeop = (fill & stroke ? "B*" : fill ? "f*" : "S");
|
||||
while(--disjunct_polygon_count_count >= 0) {
|
||||
int disj = *disjunct_polygon_counts++;
|
||||
while(disj > 0) {
|
||||
int sub = *subpolygon_counts++;
|
||||
disj -= sub;
|
||||
page << Pt(vertices->x) << ' ' << Pt(pgsz.cy - vertices->y) << " m\n";
|
||||
vertices++;
|
||||
for(; --sub > 0; vertices++)
|
||||
page << Pt(vertices->x) << ' ' << Pt(pgsz.cy - vertices->y) << " l\n";
|
||||
page << "h\n";
|
||||
}
|
||||
page << closeop << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
String PdfDraw::Finish()
|
||||
{
|
||||
if(!IsNull(page))
|
||||
PutStream(page);
|
||||
|
||||
int pagecount = offset.GetCount();
|
||||
|
||||
Vector<int> imageobj;
|
||||
for(int i = 0; i < image.GetCount(); i++) {
|
||||
Size sz = image[i].GetSize();
|
||||
Rect sr = sz & imagerect[i];
|
||||
String data;
|
||||
const Image& m = image[i];
|
||||
int mask = -1;
|
||||
int smask = -1;
|
||||
if(m.GetKind() == IMAGE_MASK) {
|
||||
for(int y = sr.top; y < sr.bottom; y++) {
|
||||
const RGBA *p = m[y] + sr.left;
|
||||
const RGBA *e = m[y] + sr.right;
|
||||
while(p < e) {
|
||||
int bit = 0x80;
|
||||
byte b = 0;
|
||||
while(bit && p < e) {
|
||||
if(p->a != 255)
|
||||
b |= bit;
|
||||
bit >>= 1;
|
||||
p++;
|
||||
}
|
||||
data.Cat(b);
|
||||
}
|
||||
}
|
||||
mask = PutStream(data, String().Cat()
|
||||
<< "/Type /XObject /Subtype /Image /Width " << sr.Width()
|
||||
<< " /Height " << sr.Height()
|
||||
<< " /BitsPerComponent 1 /ImageMask true /Decode [0 1]");
|
||||
}
|
||||
if(m.GetKind() == IMAGE_ALPHA) {
|
||||
for(int y = sr.top; y < sr.bottom; y++) {
|
||||
const RGBA *p = m[y] + sr.left;
|
||||
const RGBA *e = m[y] + sr.right;
|
||||
while(p < e)
|
||||
data.Cat((p++)->a);
|
||||
}
|
||||
smask = PutStream(data, String().Cat()
|
||||
<< "/Type /XObject /Subtype /Image /Width " << sr.Width()
|
||||
<< " /Height " << sr.Height()
|
||||
<< " /BitsPerComponent 8 /ColorSpace /DeviceGray /Decode [0 1]");
|
||||
}
|
||||
data.Clear();
|
||||
for(int y = sr.top; y < sr.bottom; y++) {
|
||||
const RGBA *p = m[y] + sr.left;
|
||||
const RGBA *e = m[y] + sr.right;
|
||||
while(p < e) {
|
||||
data.Cat(p->r);
|
||||
data.Cat(p->g);
|
||||
data.Cat(p->b);
|
||||
p++;
|
||||
}
|
||||
}
|
||||
String imgobj;
|
||||
imgobj << "/Type /XObject /Subtype /Image /Width " << sr.Width()
|
||||
<< " /Height " << sr.Height() << " /BitsPerComponent 8 /ColorSpace /DeviceRGB";
|
||||
if(mask >= 0)
|
||||
imgobj << " /Mask " << mask << " 0 R";
|
||||
if(smask >= 0)
|
||||
imgobj << " /SMask " << smask << " 0 R";
|
||||
imageobj << PutStream(data, imgobj);
|
||||
}
|
||||
|
||||
/*
|
||||
Vector<int> rgobj;
|
||||
Vector<Size> rgsz;
|
||||
Vector<int> rgx;
|
||||
for(int i = 0; i < pdffont.GetCount(); i++) {
|
||||
Font fnt = pdffont.GetKey(i);
|
||||
if(fnt.GetHeight()) {
|
||||
for(int c = 0; c < pdffont[i].GetCount(); c++) {
|
||||
RGlyph rg = RasterGlyph(fnt, pdffont[i][c]);
|
||||
int ii = rgobj.GetCount();
|
||||
rgobj << PutStream(rg.data, String().Cat()
|
||||
<< "/Type /XObject /Subtype /Image "
|
||||
<< " /Width " << rg.sz.cx << " /Height " << rg.sz.cy
|
||||
<< " /BitsPerComponent 1 /ImageMask true /Decode [0 1]");
|
||||
rgsz.Add(rg.sz);
|
||||
rgx.Add(rg.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
Vector<int> fontobj;
|
||||
for(int i = 0; i < pdffont.GetCount(); i++) {
|
||||
Font fnt = pdffont.GetKey(i);
|
||||
const Vector<wchar>& cs = pdffont[i];
|
||||
String cmap;
|
||||
cmap <<
|
||||
"/CIDInit /ProcSet findresource begin\n"
|
||||
"12 dict begin\n"
|
||||
"begincmap\n"
|
||||
"/CIDSystemInfo\n"
|
||||
"<< /Registry (Adobe)\n"
|
||||
"/Ordering (UCS)\n"
|
||||
"/Supplement 0\n"
|
||||
">> def\n"
|
||||
"/CMapName /UCS" << i << " def\n"
|
||||
"/CMapType 2 def\n"
|
||||
"1 begincodespacerange\n"
|
||||
"<00> <" << FormatIntHex(cs.GetCount() - 1, 2) << ">\n"
|
||||
"endcodespacerange\n"
|
||||
"1 beginbfrange\n"
|
||||
"<00> <" << FormatIntHex(cs.GetCount() - 1, 2) << ">\n"
|
||||
"[\n";
|
||||
for(int c = 0; c < cs.GetCount(); c++)
|
||||
cmap << '<' << FormatIntHex(cs[c], 4) << ">\n";
|
||||
cmap <<
|
||||
"]\n"
|
||||
"endbfrange\n"
|
||||
"endcmap\n"
|
||||
"CMapName currentdict /CMap defineresource pop\n"
|
||||
"end\n"
|
||||
"end\n";
|
||||
int cmapi = PutStream(cmap);
|
||||
if(fnt.GetHeight()) {
|
||||
FontInfo fi = fnt.Info();
|
||||
int t3ch = offset.GetCount() + 1;
|
||||
int fa = fi.GetHeight() - fi.GetInternal();
|
||||
String res;
|
||||
for(int c = 0; c < cs.GetCount(); c++) {
|
||||
RGlyph rg = RasterGlyph(fnt, pdffont[i][c]);
|
||||
String proc;
|
||||
proc
|
||||
<< 1000 * fi[cs[c]] / fa << " 0 0 "
|
||||
<< -1000 * fi.GetDescent() / fa << ' '
|
||||
<< 1000 * (rg.sz.cx + rg.x) / fa << ' '
|
||||
<< 1000 * rg.sz.cy / fa
|
||||
<< " d1\nq "
|
||||
<< 1000 * rg.sz.cx / fa
|
||||
<< " 0 0 "
|
||||
<< 1000 * rg.sz.cy / fa
|
||||
<< " "
|
||||
<< -1000 * rg.x / fa
|
||||
<< " "
|
||||
<< -1000 * fi.GetDescent() / fa
|
||||
<< " cm BI /W " << rg.sz.cx << " /H " << rg.sz.cy
|
||||
<< " /BPC 1 /IM true /D [0 1] ID\n"
|
||||
<< rg.data
|
||||
<< "\nEI Q"
|
||||
;
|
||||
PutStream(proc);
|
||||
}
|
||||
int charprocs = BeginObj();
|
||||
out << "<<";
|
||||
for(int c = 0; c < cs.GetCount(); c++)
|
||||
out << " /Rgch" << c << ' ' << t3ch + c<< " 0 R";
|
||||
out << " >>\n";
|
||||
EndObj();
|
||||
int encoding = BeginObj();
|
||||
out << "<< /Type /Encoding /Differences [0";
|
||||
for(int c = 0; c < cs.GetCount(); c++)
|
||||
out << " /Rgch" << c;
|
||||
out << "] >>\n";
|
||||
EndObj();
|
||||
fontobj.Add() = BeginObj();
|
||||
out <<
|
||||
"<< /Name /F" << i + 1 <<
|
||||
" /Type /Font\n"
|
||||
"/Subtype /Type3\n"
|
||||
"/FontBBox [0 0 0 0]\n"
|
||||
"/FontMatrix [0.001 0 0 0.001 0 0]\n"
|
||||
"/CharProcs " << charprocs << " 0 R\n"
|
||||
"/Encoding " << encoding << " 0 R\n"
|
||||
"/FirstChar 0\n"
|
||||
"/LastChar " << cs.GetCount() - 1 << "\n"
|
||||
"/Widths [";
|
||||
for(int i = 0; i < cs.GetCount(); i++)
|
||||
out << ' ' << 1000 * fi[cs[i]] / fa;
|
||||
out <<
|
||||
"]\n";
|
||||
out << "/Resources << /ProcSet [ /PDF /Text /ImageB ] >>\n"
|
||||
<< "/FirstChar 0 /LastChar " << cs.GetCount() - 1 <<" /ToUnicode "
|
||||
<< cmapi
|
||||
<< " 0 R\n>>\n";
|
||||
EndObj();
|
||||
}
|
||||
else {
|
||||
#ifdef PLATFORM_POSIX
|
||||
FontInfo fi = pdffont.GetKey(i).Info();
|
||||
String fontbuffer = LoadFile(fi.GetFileName());
|
||||
#endif
|
||||
#ifdef PLATFORM_WIN32
|
||||
ScreenDraw sd;
|
||||
sd.SetFont(pdffont.GetKey(i));
|
||||
|
||||
int size = GetFontData(sd.GetHandle(), 0, 0, NULL, 0);
|
||||
if(size == GDI_ERROR) {
|
||||
LLOG("PdfDraw::Finish: GDI_ERROR on font " << pdffont.GetKey(i));
|
||||
return Null;
|
||||
}
|
||||
StringBuffer fontbuffer(size);
|
||||
GetFontData(sd.GetHandle(), 0, 0, fontbuffer, size);
|
||||
#endif
|
||||
|
||||
TTFReader ttf;
|
||||
if(!ttf.Open(fontbuffer))
|
||||
return Null;
|
||||
|
||||
|
||||
String name = FormatIntAlpha(i + 1, true);
|
||||
name.Cat('A', 6 - name.GetLength());
|
||||
name << '+' << ttf.ps_name;
|
||||
|
||||
int fonti = PutStream(ttf.Subset(cs));
|
||||
|
||||
BeginObj();
|
||||
int ascent = ttf.hhea.ascent * 1000 / ttf.head.unitsPerEm;
|
||||
int descent = ttf.hhea.descent * 1000 / ttf.head.unitsPerEm;
|
||||
out <<
|
||||
"<< /Type /FontDescriptor\n"
|
||||
"/FontName /" << name << "\n"
|
||||
"/Flags 4\n"
|
||||
"/FontBBox [ -1000 " << descent << " 3000 " << ascent << " ]\n" //?????
|
||||
"/ItalicAngle " << ttf.post.italicAngle / 65536.0 << "\n"
|
||||
"/Ascent " << ascent << "\n"
|
||||
"/Descent " << -descent << "\n"
|
||||
"/CapHeight " << ttf.hhea.ascent * 1000 / ttf.head.unitsPerEm << "\n"
|
||||
"/StemV 80\n"
|
||||
"/FontFile2 " << fonti << " 0 R\n" <<
|
||||
">>\n";
|
||||
EndObj();
|
||||
|
||||
fontobj.Add() = BeginObj();
|
||||
out <<
|
||||
"<< /Type /Font\n"
|
||||
"/Subtype /TrueType\n"
|
||||
"/BaseFont /" << name << "\n"
|
||||
"/FirstChar 0\n"
|
||||
"/LastChar " << cs.GetCount() - 1 << "\n"
|
||||
"/Widths [ ";
|
||||
for(int i = 0; i < cs.GetCount(); i++)
|
||||
out << ttf.GetAdvanceWidth(cs[i]) * 1000 / ttf.head.unitsPerEm << ' ';
|
||||
out <<
|
||||
"]\n"
|
||||
"/FontDescriptor " << fonti + 1 << " 0 R\n"
|
||||
"/ToUnicode " << cmapi << " 0 R\n" <<
|
||||
">>\n";
|
||||
EndObj();
|
||||
}
|
||||
}
|
||||
|
||||
int pages = BeginObj();
|
||||
out << "<< /Type /Pages\n"
|
||||
<< "/Kids [";
|
||||
for(int i = 0; i < pagecount; i++)
|
||||
out << i + pages + 1 << " 0 R ";
|
||||
out << "]\n"
|
||||
<< "/Count " << pagecount << "\n"
|
||||
<< "/Resources << /ProcSet [ /PDF /Text /ImageB /ImageC ]\n";
|
||||
if(pdffont.GetCount()) {
|
||||
out << "/Font << ";
|
||||
for(int i = 0; i < pdffont.GetCount(); i++)
|
||||
out << "/F" << i + 1 << ' ' << fontobj[i] << " 0 R ";
|
||||
out << ">>\n";
|
||||
}
|
||||
if(!imageobj.IsEmpty()) {
|
||||
out << "/XObject << ";
|
||||
for(int i = 0; i < imageobj.GetCount(); i++)
|
||||
out << "/Image" << i + 1 << ' ' << imageobj[i] << " 0 R ";
|
||||
out << ">>\n";
|
||||
}
|
||||
out << ">> >>\n";
|
||||
EndObj();
|
||||
for(int i = 0; i < pagecount; i++) {
|
||||
BeginObj();
|
||||
out << "<< /Type /Page\n"
|
||||
<< "/Parent " << pages << " 0 R\n"
|
||||
<< "/MediaBox [0 0 " << Pt(pgsz.cx) << ' ' << Pt(pgsz.cy) << "]\n"
|
||||
<< "/Contents " << i + 1 << " 0 R\n"
|
||||
<< ">>\n";
|
||||
EndObj();
|
||||
}
|
||||
int outlines = BeginObj();
|
||||
out << "<< /Type /Outlines\n"
|
||||
"/Count 0\n"
|
||||
">>\n";
|
||||
EndObj();
|
||||
int catalog = BeginObj();
|
||||
out << "<< /Type /Catalog\n"
|
||||
<< "/Outlines " << outlines << " 0 R\n"
|
||||
<< "/Pages " << pages << " 0 R\n"
|
||||
<< ">>\n";
|
||||
EndObj();
|
||||
int startxref = out.GetCount();
|
||||
out << "xref\n"
|
||||
<< "0 " << offset.GetCount() + 1 << "\n";
|
||||
out << "0000000000 65535 f\r\n";
|
||||
for(int i = 0; i < offset.GetCount(); i++)
|
||||
out << Sprintf("%010d 00000 n\r\n", offset[i]);
|
||||
out << "\n"
|
||||
<< "trailer\n"
|
||||
<< "<< /Size " << offset.GetCount() + 1 << "\n"
|
||||
<< "/Root " << catalog << " 0 R\n"
|
||||
<< ">>\n"
|
||||
<< "startxref\r\n"
|
||||
<< startxref << "\r\n"
|
||||
<< "%%EOF\r\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
343
uppsrc/PdfDraw/PdfDraw.h
Normal file
343
uppsrc/PdfDraw/PdfDraw.h
Normal file
|
|
@ -0,0 +1,343 @@
|
|||
#ifndef _PDF_pdf_h_
|
||||
#define _PDF_pdf_h_
|
||||
|
||||
#include <Draw/Draw.h>
|
||||
#include <plugin/z/z.h>
|
||||
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
class TTFReader {
|
||||
struct TTFStream {
|
||||
struct Fail {};
|
||||
|
||||
virtual void Raw(void *ptr, int count) = 0;
|
||||
|
||||
TTFStream& operator%(byte& q);
|
||||
TTFStream& operator%(int32& q);
|
||||
TTFStream& operator%(uint32& q);
|
||||
TTFStream& operator%(int16& q);
|
||||
TTFStream& operator%(uint16& q);
|
||||
|
||||
virtual ~TTFStream() {}
|
||||
};
|
||||
|
||||
struct TTFStreamIn : TTFStream {
|
||||
const char *beg;
|
||||
const char *s;
|
||||
const char *lim;
|
||||
|
||||
virtual void Raw(void *ptr, int count);
|
||||
|
||||
void Seek(int offset);
|
||||
int Get8();
|
||||
int Get16();
|
||||
int Get32();
|
||||
String Get(int n);
|
||||
|
||||
virtual ~TTFStreamIn() {}
|
||||
};
|
||||
|
||||
struct TTFStreamOut : TTFStream {
|
||||
String out;
|
||||
|
||||
virtual void Raw(void *ptr, int count) { out.Cat((const char *)ptr, count); }
|
||||
|
||||
void Put8(int data) { out.Cat(data); }
|
||||
void Put16(int data) { Put8(HIBYTE(data)); Put8(LOBYTE(data)); }
|
||||
void Put32(int data) { Put16(HIWORD(data)); Put16(LOWORD(data)); }
|
||||
void Put(const String& s) { out.Cat(s); }
|
||||
|
||||
operator String() const { return out; }
|
||||
|
||||
virtual ~TTFStreamOut() {}
|
||||
};
|
||||
|
||||
String font;
|
||||
|
||||
struct Table : Moveable<Table> {
|
||||
int offset;
|
||||
int length;
|
||||
};
|
||||
VectorMap<String, Table> table;
|
||||
|
||||
word zero[256];
|
||||
word *cmap[256];
|
||||
|
||||
struct GlyphInfo : Moveable<GlyphInfo> {
|
||||
int offset;
|
||||
int size;
|
||||
uint16 advanceWidth;
|
||||
int16 leftSideBearing;
|
||||
};
|
||||
|
||||
Vector<GlyphInfo> glyphinfo;
|
||||
|
||||
void SetGlyph(wchar ch, word glyph);
|
||||
|
||||
struct Fail {};
|
||||
|
||||
static void Error() { throw Fail(); }
|
||||
|
||||
int Peek8(const char *s);
|
||||
int Peek16(const char *s);
|
||||
int Peek32(const char *s);
|
||||
int Peek8(const char *s, int i);
|
||||
int Peek16(const char *s, int i);
|
||||
int Peek32(const char *s, int i);
|
||||
int Read8(const char *&s);
|
||||
int Read16(const char *&s);
|
||||
int Read32(const char *&s);
|
||||
String Read(const char *&s, int n);
|
||||
|
||||
void Free();
|
||||
void Reset();
|
||||
|
||||
const char *Seek(const char *tab, int& len);
|
||||
const char *Seek(const char *tab);
|
||||
void Seek(const char *tab, TTFStreamIn& s);
|
||||
String GetTable(const char *tab);
|
||||
|
||||
enum {
|
||||
ARG_1_AND_2_ARE_WORDS = (1<<0),
|
||||
ARGS_ARE_XY_VALUES = (1<<1),
|
||||
ROUND_XY_TO_GRID = (1<<2),
|
||||
WE_HAVE_A_SCALE = (1<<3),
|
||||
MORE_COMPONENTS = (1<<5),
|
||||
WE_HAVE_AN_X_AND_Y_SCALE = (1<<6),
|
||||
WE_HAVE_A_TWO_BY_TWO = (1<<7),
|
||||
WE_HAVE_INSTRUCTIONS = (1<<8),
|
||||
USE_MY_METRICS = (1<<9),
|
||||
};
|
||||
|
||||
struct NewTable {
|
||||
String name;
|
||||
String data;
|
||||
dword checksum;
|
||||
};
|
||||
|
||||
static void Add(Array<NewTable>& t, const char *name, const String& data);
|
||||
static void Set(NewTable& m, const String& data);
|
||||
static String CreateHeader(const Array<NewTable>& t);
|
||||
|
||||
static inline int Copy8(TTFStreamOut& out, TTFStreamIn& in)
|
||||
{ int q = in.Get8(); out.Put8(q); return q; }
|
||||
static inline int Copy16(TTFStreamOut& out, TTFStreamIn& in)
|
||||
{ int q = in.Get16(); out.Put16(q); return q; }
|
||||
static inline int Copy32(TTFStreamOut& out, TTFStreamIn& in)
|
||||
{ int q = in.Get32(); out.Put32(q); return q; }
|
||||
static inline String Copy(TTFStreamOut& out, TTFStreamIn& in, int n)
|
||||
{ String q = in.Get(n); out.Put(q); return q; }
|
||||
|
||||
public:
|
||||
struct Head {
|
||||
dword version;
|
||||
dword fontRevision;
|
||||
uint32 checkSumAdjustment;
|
||||
uint32 magicNumber;
|
||||
uint16 flags;
|
||||
uint16 unitsPerEm;
|
||||
byte created[8];
|
||||
byte modified[8];
|
||||
int16 xMin;
|
||||
int16 yMin;
|
||||
int16 xMax;
|
||||
int16 yMax;
|
||||
uint16 macStyle;
|
||||
uint16 lowestRecPPEM;
|
||||
int16 fontDirectionHint;
|
||||
int16 indexToLocFormat;
|
||||
int16 glyphDataFormat;
|
||||
|
||||
void Serialize(TTFStream& s);
|
||||
};
|
||||
|
||||
struct Hhea {
|
||||
uint32 version;
|
||||
int16 ascent;
|
||||
int16 descent;
|
||||
int16 lineGap;
|
||||
uint16 advanceWidthMax;
|
||||
int16 minLeftSideBearing;
|
||||
int16 minRightSideBearing;
|
||||
int16 xMaxExtent;
|
||||
int16 caretSlopeRise;
|
||||
int16 caretSlopeRun;
|
||||
int16 caretOffset;
|
||||
int16 reserved1;
|
||||
int16 reserved2;
|
||||
int16 reserved3;
|
||||
int16 reserved4;
|
||||
int16 metricDataFormat;
|
||||
uint16 numOfLongHorMetrics;
|
||||
|
||||
void Serialize(TTFStream& s);
|
||||
};
|
||||
|
||||
struct Maxp {
|
||||
uint32 version;
|
||||
uint16 numGlyphs;
|
||||
uint16 maxPoints;
|
||||
uint16 maxContours;
|
||||
uint16 maxComponentPoints;
|
||||
uint16 maxComponentContours;
|
||||
uint16 maxZones;
|
||||
uint16 maxTwilightPoints;
|
||||
uint16 maxStorage;
|
||||
uint16 maxFunctionDefs;
|
||||
uint16 maxInstructionDefs;
|
||||
uint16 maxStackElements;
|
||||
uint16 maxSizeOfInstructions;
|
||||
uint16 maxComponentElements;
|
||||
uint16 maxComponentDepth;
|
||||
|
||||
void Serialize(TTFStream& s);
|
||||
};
|
||||
|
||||
struct Post {
|
||||
uint32 format;
|
||||
int32 italicAngle;
|
||||
int16 underlinePosition;
|
||||
int16 underlineThickness;
|
||||
uint16 isFixedPitch;
|
||||
uint16 reserved;
|
||||
uint32 minMemType42;
|
||||
uint32 maxMemType42;
|
||||
uint32 minMemType1;
|
||||
uint32 maxMemType1;
|
||||
|
||||
void Serialize(TTFStream& s);
|
||||
};
|
||||
|
||||
Head head;
|
||||
Hhea hhea;
|
||||
Maxp maxp;
|
||||
Post post;
|
||||
String ps_name;
|
||||
|
||||
int GetGlyph(wchar chr) { return cmap[HIBYTE(chr)][LOBYTE(chr)]; }
|
||||
word GetAdvanceWidth(wchar chr) { return glyphinfo[GetGlyph(chr)].advanceWidth; }
|
||||
|
||||
String Subset(const Vector<wchar>& chars, int first = 0, bool os2 = false);
|
||||
bool Open(const String& fnt, bool symbol = false, bool justcheck = false);
|
||||
|
||||
TTFReader();
|
||||
~TTFReader();
|
||||
};
|
||||
|
||||
class PdfDraw : public Draw {
|
||||
public:
|
||||
virtual dword GetInfo() const;
|
||||
virtual Size GetPageSize() const;
|
||||
|
||||
virtual void StartPage();
|
||||
virtual void EndPage();
|
||||
|
||||
virtual void BeginOp();
|
||||
virtual void EndOp();
|
||||
virtual void OffsetOp(Point p);
|
||||
virtual bool ClipOp(const Rect& r);
|
||||
virtual bool ClipoffOp(const Rect& r);
|
||||
virtual bool ExcludeClipOp(const Rect& r);
|
||||
virtual bool IntersectClipOp(const Rect& r);
|
||||
virtual bool IsPaintingOp(const Rect& r) const;
|
||||
|
||||
virtual void DrawRectOp(int x, int y, int cx, int cy, Color color);
|
||||
virtual void DrawImageOp(int x, int y, int cx, int cy, const Image& img, const Rect& src, Color color);
|
||||
virtual void DrawLineOp(int x1, int y1, int x2, int y2, int width, Color color);
|
||||
virtual void DrawPolyPolylineOp(const Point *vertices, int vertex_count,
|
||||
const int *counts, int count_count,
|
||||
int width, Color color, Color doxor);
|
||||
virtual void DrawPolyPolyPolygonOp(const Point *vertices, int vertex_count,
|
||||
const int *subpolygon_counts, int scc,
|
||||
const int *disjunct_polygon_counts, int dpcc,
|
||||
Color color, int width, Color outline,
|
||||
uint64 pattern, Color doxor);
|
||||
virtual void DrawEllipseOp(const Rect& r, Color color, int pen, Color pencolor);
|
||||
virtual void DrawArcOp(const Rect& rc, Point start, Point end, int width, Color color);
|
||||
virtual void DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
|
||||
Color ink, int n, const int *dx);
|
||||
|
||||
private:
|
||||
struct CharPos : Moveable<CharPos> { word fi, ci; };
|
||||
|
||||
struct OutlineInfo : Moveable<OutlineInfo> {
|
||||
bool ttf;
|
||||
bool sitalic;
|
||||
};
|
||||
|
||||
VectorMap<Font, OutlineInfo> outline_info;
|
||||
VectorMap<Font, Vector<wchar> > pdffont;
|
||||
VectorMap<Font, VectorMap<wchar, CharPos> > fontchars;
|
||||
Vector<Image> image;
|
||||
Vector<Rect> imagerect;
|
||||
|
||||
Vector<int> offset;
|
||||
String out;
|
||||
String page;
|
||||
Size pgsz;
|
||||
Color rgcolor;
|
||||
Color RGcolor;
|
||||
int fontid;
|
||||
double textht;
|
||||
double linewidth;
|
||||
int margin;
|
||||
|
||||
inline double Pt(double dot) { return 0.12 * dot; }
|
||||
|
||||
int Pos() { return offset.GetCount() + 1; }
|
||||
int BeginObj();
|
||||
void EndObj();
|
||||
int PutStream(const String& data, const String& keys = Null);
|
||||
|
||||
void PutRect(const Rect& rc);
|
||||
void PutrgColor(Color rg);
|
||||
void PutRGColor(Color RG);
|
||||
void PutFontHeight(int fi, double ht);
|
||||
void PutLineWidth(int lw);
|
||||
|
||||
CharPos GetCharPos(Font fnt, wchar chr);
|
||||
void FlushText(int dx, int fi, int height, const String& txt);
|
||||
static String PdfColor(Color c);
|
||||
|
||||
OutlineInfo GetOutlineInfo(Font fnt);
|
||||
|
||||
struct M22 {
|
||||
double a, b, c, d;
|
||||
|
||||
void Mul(double a1, double b1, double c1, double d1) {
|
||||
M22 t;
|
||||
t.a = a * a1 + b * c1;
|
||||
t.b = a * b1 + b * d1;
|
||||
t.c = c * a1 + d * c1;
|
||||
t.d = c * b1 + d * d1;
|
||||
*this = t;
|
||||
}
|
||||
|
||||
M22(double a, double b, double c, double d) : a(a), b(b), c(c), d(d) {}
|
||||
M22() : a(1), b(0), c(0), d(1) {}
|
||||
};
|
||||
|
||||
void Init(int pagecx, int pagecy, int margin);
|
||||
|
||||
struct RGlyph : Moveable<RGlyph> {
|
||||
String data;
|
||||
Size sz;
|
||||
int x;
|
||||
};
|
||||
|
||||
RGlyph RasterGlyph(Font fnt, int chr);
|
||||
|
||||
public:
|
||||
String Finish();
|
||||
void Clear();
|
||||
|
||||
PdfDraw(int pagecx, int pagecy) { Init(pagecx, pagecy, 0); }
|
||||
PdfDraw(Size pgsz = Size(5100, 6600)) { Init(pgsz.cx, pgsz.cy, 0); }
|
||||
};
|
||||
|
||||
String Pdf(const Array<Drawing>& report, Size pagesize, int margin);
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
16
uppsrc/PdfDraw/PdfDraw.upp
Normal file
16
uppsrc/PdfDraw/PdfDraw.upp
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
description "PDF output as Draw derived class\377128,0,255";
|
||||
|
||||
uses
|
||||
Draw;
|
||||
|
||||
file
|
||||
PdfDraw.h,
|
||||
TTFStream.cpp,
|
||||
TTFStruct.cpp,
|
||||
TTFReader.cpp,
|
||||
TTFSubset.cpp,
|
||||
PdfDraw.cpp,
|
||||
PdfReport.icpp,
|
||||
Info readonly separator,
|
||||
Copying;
|
||||
|
||||
21
uppsrc/PdfDraw/PdfReport.icpp
Normal file
21
uppsrc/PdfDraw/PdfReport.icpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#include "PdfDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
String Pdf(const Array<Drawing>& report, Size sz, int margin)
|
||||
{
|
||||
PdfDraw w(sz + 2 * margin);
|
||||
for(int i = 0; i < report.GetCount(); i++) {
|
||||
w.StartPage();
|
||||
w.DrawDrawing(margin, margin, sz.cx, sz.cy, report[i]);
|
||||
w.EndPage();
|
||||
}
|
||||
return w.Finish();
|
||||
}
|
||||
|
||||
INITBLOCK
|
||||
{
|
||||
SetDrawingToPdfFn(Pdf);
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
311
uppsrc/PdfDraw/TTFReader.cpp
Normal file
311
uppsrc/PdfDraw/TTFReader.cpp
Normal file
|
|
@ -0,0 +1,311 @@
|
|||
#include "PdfDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#define LLOG(x) // LOG(x)
|
||||
#define LDUMP(x) // LLOG(#x << " = " << x);
|
||||
|
||||
int TTFReader::Peek8(const char *s)
|
||||
{
|
||||
if(s + 1 > font.End())
|
||||
Error();
|
||||
return (byte)*s;
|
||||
}
|
||||
|
||||
int TTFReader::Peek16(const char *s)
|
||||
{
|
||||
if(s + 2 > font.End())
|
||||
Error();
|
||||
return ((byte)s[0] << 8) | (byte)s[1];
|
||||
}
|
||||
|
||||
int TTFReader::Peek32(const char *s)
|
||||
{
|
||||
if(s + 4 > font.End())
|
||||
Error();
|
||||
return ((byte)s[0] << 24) | ((byte)s[1] << 16) | ((byte)s[2] << 8) | (byte)s[3];
|
||||
}
|
||||
|
||||
int TTFReader::Peek8(const char *s, int i)
|
||||
{
|
||||
return Peek16(s + i);
|
||||
}
|
||||
|
||||
int TTFReader::Peek16(const char *s, int i)
|
||||
{
|
||||
return Peek16(s + 2 * i);
|
||||
}
|
||||
|
||||
int TTFReader::Peek32(const char *s, int i)
|
||||
{
|
||||
return Peek32(s + 4 * i);
|
||||
}
|
||||
|
||||
int TTFReader::Read8(const char *&s)
|
||||
{
|
||||
int q = byte(*s); s++; return q;
|
||||
}
|
||||
|
||||
int TTFReader::Read16(const char *&s)
|
||||
{
|
||||
int q = Peek16(s); s += 2; return q;
|
||||
}
|
||||
|
||||
int TTFReader::Read32(const char *&s)
|
||||
{
|
||||
int q = Peek32(s); s += 4; return q;
|
||||
}
|
||||
|
||||
String TTFReader::Read(const char *&s, int n)
|
||||
{
|
||||
if(s + n > font.End())
|
||||
Error();
|
||||
String q(s, n);
|
||||
s += n;
|
||||
return q;
|
||||
}
|
||||
|
||||
void TTFReader::Reset()
|
||||
{
|
||||
memset(zero, 0, sizeof(zero));
|
||||
for(int i = 0; i < 256; i++)
|
||||
cmap[i] = zero;
|
||||
}
|
||||
|
||||
void TTFReader::Free()
|
||||
{
|
||||
for(int i = 0; i < 256; i++)
|
||||
if(cmap[i] != zero)
|
||||
delete[] cmap[i];
|
||||
}
|
||||
|
||||
void TTFReader::SetGlyph(wchar chr, word glyph)
|
||||
{
|
||||
int h = HIBYTE(chr);
|
||||
if(cmap[h] == zero)
|
||||
memset(cmap[h] = new word[256], 0, 256 * sizeof(word));
|
||||
cmap[h][LOBYTE(chr)] = glyph;
|
||||
}
|
||||
|
||||
const char *TTFReader::Seek(const char *tab, int& len)
|
||||
{
|
||||
ASSERT(strlen(tab) == 4);
|
||||
int q = table.Find(tab);
|
||||
if(q < 0)
|
||||
Error();
|
||||
len = table[q].length;
|
||||
return ~font + table[q].offset;
|
||||
}
|
||||
|
||||
const char *TTFReader::Seek(const char *tab)
|
||||
{
|
||||
int dummy;
|
||||
return Seek(tab, dummy);
|
||||
}
|
||||
|
||||
void TTFReader::Seek(const char *tab, TTFStreamIn& s)
|
||||
{
|
||||
int len;
|
||||
s.beg = s.s = Seek(tab, len);
|
||||
s.lim = s.s + len;
|
||||
}
|
||||
|
||||
String TTFReader::GetTable(const char *tab)
|
||||
{
|
||||
ASSERT(strlen(tab) == 4);
|
||||
int q = table.Find(tab);
|
||||
if(q < 0)
|
||||
return Null;
|
||||
return String(~font + table[q].offset, table[q].length);
|
||||
}
|
||||
|
||||
bool TTFReader::Open(const String& fnt, bool symbol, bool justcheck)
|
||||
{
|
||||
try {
|
||||
int i;
|
||||
Free();
|
||||
Reset();
|
||||
table.Clear();
|
||||
glyphinfo.Clear();
|
||||
font = fnt;
|
||||
const char *s = fnt;
|
||||
int q = Read32(s);
|
||||
if(q != 0x74727565 && q != 0x00010000)
|
||||
Error();
|
||||
int n = Read16(s);
|
||||
s += 6;
|
||||
while(n--) {
|
||||
Table& t = table.Add(Read(s, 4));
|
||||
s += 4;
|
||||
t.offset = Read32(s);
|
||||
t.length = Read32(s);
|
||||
}
|
||||
for(i = 0; i < table.GetCount(); i++)
|
||||
LLOG("table: " << table.GetKey(i) << " offset: " << table[i].offset << " length: " << table[i].length);
|
||||
|
||||
TTFStreamIn is;
|
||||
Seek("head", is);
|
||||
head.Serialize(is);
|
||||
if(head.magicNumber != 0x5F0F3CF5)
|
||||
Error();
|
||||
|
||||
LDUMP(head.unitsPerEm);
|
||||
LDUMP(head.xMin);
|
||||
LDUMP(head.yMin);
|
||||
LDUMP(head.xMax);
|
||||
LDUMP(head.yMax);
|
||||
LDUMP(head.indexToLocFormat);
|
||||
|
||||
Seek("maxp", is);
|
||||
maxp.Serialize(is);
|
||||
LDUMP(maxp.numGlyphs);
|
||||
|
||||
Seek("post", is);
|
||||
post.Serialize(is);
|
||||
// LLOGHEXLDUMP(is.s, is.lim - is.s);
|
||||
LDUMP((post.format >> 16));
|
||||
LDUMP(post.italicAngle);
|
||||
LDUMP(post.italicAngle);
|
||||
LDUMP(post.underlinePosition);
|
||||
LDUMP(post.underlineThickness);
|
||||
LDUMP(post.italicAngle);
|
||||
|
||||
if(justcheck)
|
||||
return true;
|
||||
|
||||
Seek("hhea", is);
|
||||
hhea.Serialize(is);
|
||||
LDUMP(hhea.ascent);
|
||||
LDUMP(hhea.descent);
|
||||
LDUMP(hhea.lineGap);
|
||||
LDUMP(hhea.advanceWidthMax);
|
||||
LDUMP(hhea.numOfLongHorMetrics);
|
||||
|
||||
if(hhea.numOfLongHorMetrics > maxp.numGlyphs)
|
||||
Error();
|
||||
|
||||
glyphinfo.SetCount(maxp.numGlyphs);
|
||||
|
||||
s = Seek("hmtx");
|
||||
int aw = 0;
|
||||
for(i = 0; i < hhea.numOfLongHorMetrics; i++) {
|
||||
aw = glyphinfo[i].advanceWidth = (uint16)Read16(s);
|
||||
glyphinfo[i].leftSideBearing = (int16)Read16(s);
|
||||
}
|
||||
for(; i < maxp.numGlyphs; i++) {
|
||||
glyphinfo[i].advanceWidth = aw;
|
||||
glyphinfo[i].leftSideBearing = (int16)Read16(s);
|
||||
}
|
||||
|
||||
s = Seek("loca");
|
||||
for(i = 0; i < maxp.numGlyphs; i++)
|
||||
if(head.indexToLocFormat) {
|
||||
glyphinfo[i].offset = Peek32(s, i);
|
||||
glyphinfo[i].size = Peek32(s, i + 1) - glyphinfo[i].offset;
|
||||
}
|
||||
else {
|
||||
glyphinfo[i].offset = 2 * (word)Peek16(s, i);
|
||||
glyphinfo[i].size = 2 * (word)Peek16(s, i + 1) - glyphinfo[i].offset;
|
||||
}
|
||||
|
||||
for(i = 0; i < maxp.numGlyphs; i++)
|
||||
LLOG(i << " advance: " << glyphinfo[i].advanceWidth << ", left: " << glyphinfo[i].leftSideBearing
|
||||
<< ", offset: " << glyphinfo[i].offset << ", size: " << glyphinfo[i].size);
|
||||
|
||||
s = Seek("cmap");
|
||||
const char *p = s;
|
||||
p += 2;
|
||||
n = Read16(p);
|
||||
while(n--) {
|
||||
int pid = Read16(p);
|
||||
int psid = Read16(p);
|
||||
int offset = Read32(p);
|
||||
LLOG("cmap pid: " << pid << " psid: " << psid << " format: " << Peek16(s + offset));
|
||||
//Test with Symbol font !!!; improve - Unicode first, 256 bytes later..., symbol...
|
||||
if(symbol) {
|
||||
if(pid == 1 && psid == 0 && Peek16(s + offset) == 0) {
|
||||
LLOG("Reading symbol table");
|
||||
p = s + offset + 6;
|
||||
for(int i = 0; i < 256; i++)
|
||||
SetGlyph(i, (byte)p[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
if(pid == 3 && psid == 1) {
|
||||
p = s + offset;
|
||||
n = Peek16(p + 6) >> 1;
|
||||
LLOG("Found UNICODE encoding, offset " << offset << ", segments " << n);
|
||||
const char *seg_end = p + 14;
|
||||
const char *seg_start = seg_end + 2 * n + 2;
|
||||
const char *idDelta = seg_start + 2 * n;
|
||||
const char *idRangeOffset = idDelta + 2 * n;
|
||||
for(int i = 0; i < n; i++) {
|
||||
int start = Peek16(seg_start, i);
|
||||
int end = Peek16(seg_end, i);
|
||||
int delta = Peek16(idDelta, i);
|
||||
int ro = Peek16(idRangeOffset, i);
|
||||
if (ro && delta == 0) {
|
||||
LLOG("RangeOffset start: " << start << ", end: " << end << ", delta: " << (int16)delta);
|
||||
LLOG("ro " << ro);
|
||||
const char *q = idRangeOffset + 2 * i + ro;
|
||||
for(int c = start; c <= end; c++) {
|
||||
SetGlyph(c, (word)Read16(q));
|
||||
}
|
||||
}
|
||||
else {
|
||||
LLOG("start: " << start << ", end: " << end << ", delta: " << (int16)delta);
|
||||
for(int c = start; c <= end; c++)
|
||||
SetGlyph(c, c + delta);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const char *strings = Seek("name");
|
||||
s = strings + 2;
|
||||
int count = Read16(s);
|
||||
strings += (word)Read16(s);
|
||||
for(int i = 0; i < count; i++) {
|
||||
int platform = Read16(s);
|
||||
s += 4;
|
||||
if(Read16(s) == 6) {
|
||||
int len = Read16(s);
|
||||
int offset = Read16(s);
|
||||
if(platform == 1)
|
||||
ps_name = String(strings + offset, len);
|
||||
else {
|
||||
s = strings + offset;
|
||||
len >>= 1;
|
||||
while(len--)
|
||||
ps_name.Cat(Read16(s));
|
||||
}
|
||||
break;
|
||||
}
|
||||
s += 4;
|
||||
}
|
||||
LDUMP(ps_name);
|
||||
}
|
||||
catch(Fail) {
|
||||
return false;
|
||||
}
|
||||
catch(TTFStream::Fail) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TTFReader::TTFReader()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
TTFReader::~TTFReader()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
110
uppsrc/PdfDraw/TTFStream.cpp
Normal file
110
uppsrc/PdfDraw/TTFStream.cpp
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
#include "PdfDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
TTFReader::TTFStream& TTFReader::TTFStream::operator%(byte& q) {
|
||||
Raw(&q, 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
#ifdef CPU_LE
|
||||
TTFReader::TTFStream& TTFReader::TTFStream::operator%(int32& q) {
|
||||
byte *h = (byte *)&q;
|
||||
*this % h[3] % h[2] % h[1] % h[0];
|
||||
return *this;
|
||||
}
|
||||
|
||||
TTFReader::TTFStream& TTFReader::TTFStream::operator%(uint32& q) {
|
||||
byte *h = (byte *)&q;
|
||||
*this % h[3] % h[2] % h[1] % h[0];
|
||||
return *this;
|
||||
}
|
||||
|
||||
TTFReader::TTFStream& TTFReader::TTFStream::operator%(int16& q) {
|
||||
byte *h = (byte *)&q;
|
||||
*this % h[1] % h[0];
|
||||
return *this;
|
||||
}
|
||||
|
||||
TTFReader::TTFStream& TTFReader::TTFStream::operator%(uint16& q) {
|
||||
byte *h = (byte *)&q;
|
||||
*this % h[1] % h[0];
|
||||
return *this;
|
||||
}
|
||||
#else
|
||||
TTFReader::TTFStream& TTFReader::TTFStream::operator%(int32& q) {
|
||||
byte *h = (byte *)&q;
|
||||
*this % h[0] % h[1] % h[2] % h[3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
TTFReader::TTFStream& TTFReader::TTFStream::operator%(uint32& q) {
|
||||
byte *h = (byte *)&q;
|
||||
*this % h[0] % h[1] % h[2] % h[3];
|
||||
return *this;
|
||||
}
|
||||
|
||||
TTFReader::TTFStream& TTFReader::TTFStream::operator%(int16& q) {
|
||||
byte *h = (byte *)&q;
|
||||
*this % h[0] % h[1];
|
||||
return *this;
|
||||
}
|
||||
|
||||
TTFReader::TTFStream& TTFReader::TTFStream::operator%(uint16& q) {
|
||||
byte *h = (byte *)&q;
|
||||
*this % h[0] % h[1];
|
||||
return *this;
|
||||
}
|
||||
#endif
|
||||
|
||||
void TTFReader::TTFStreamIn::Seek(int offset)
|
||||
{
|
||||
ASSERT(offset >= 0 && offset < lim - beg);
|
||||
s = beg + offset;
|
||||
}
|
||||
|
||||
int TTFReader::TTFStreamIn::Get8()
|
||||
{
|
||||
if(s + 1 > lim)
|
||||
throw Fail();
|
||||
int q = (byte)*s;
|
||||
s++;
|
||||
return q;
|
||||
}
|
||||
|
||||
int TTFReader::TTFStreamIn::Get16()
|
||||
{
|
||||
if(s + 2 > lim)
|
||||
throw Fail();
|
||||
int q = ((byte)s[0] << 8) | (byte)s[1];
|
||||
s += 2;
|
||||
return q;
|
||||
|
||||
}
|
||||
|
||||
int TTFReader::TTFStreamIn::Get32()
|
||||
{
|
||||
if(s + 4 > lim)
|
||||
throw Fail();
|
||||
int q = ((byte)s[0] << 24) | ((byte)s[1] << 16) | ((byte)s[2] << 8) | (byte)s[3];
|
||||
s += 2;
|
||||
return q;
|
||||
}
|
||||
|
||||
String TTFReader::TTFStreamIn::Get(int n)
|
||||
{
|
||||
if(s + n > lim)
|
||||
throw Fail();
|
||||
String r(s, n);
|
||||
s += n;
|
||||
return r;
|
||||
}
|
||||
|
||||
void TTFReader::TTFStreamIn::Raw(void *ptr, int count) {
|
||||
if(s + count > lim)
|
||||
throw Fail();
|
||||
memcpy(ptr, s, count);
|
||||
s += count;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
37
uppsrc/PdfDraw/TTFStruct.cpp
Normal file
37
uppsrc/PdfDraw/TTFStruct.cpp
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
#include "PdfDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
void TTFReader::Head::Serialize(TTFStream& s)
|
||||
{
|
||||
s % version % fontRevision % checkSumAdjustment % magicNumber % flags % unitsPerEm;
|
||||
s.Raw(created, 8);
|
||||
s.Raw(modified, 8);
|
||||
s % xMin % yMin % xMax % yMax % macStyle % lowestRecPPEM % fontDirectionHint
|
||||
% indexToLocFormat % glyphDataFormat;
|
||||
}
|
||||
|
||||
void TTFReader::Hhea::Serialize(TTFStream& s)
|
||||
{
|
||||
reserved1 = reserved2 = reserved3 = reserved4 = 0;
|
||||
s % version % ascent % descent % lineGap % advanceWidthMax % minLeftSideBearing
|
||||
% minRightSideBearing % xMaxExtent % caretSlopeRise % caretSlopeRun % caretOffset
|
||||
% reserved1 % reserved2 % reserved3 % reserved4 % metricDataFormat % numOfLongHorMetrics;
|
||||
}
|
||||
|
||||
void TTFReader::Maxp::Serialize(TTFStream& s)
|
||||
{
|
||||
s % version % numGlyphs % maxPoints % maxContours % maxComponentPoints
|
||||
% maxComponentContours % maxZones % maxTwilightPoints % maxStorage
|
||||
% maxFunctionDefs % maxInstructionDefs % maxStackElements
|
||||
% maxSizeOfInstructions % maxComponentElements % maxComponentDepth;
|
||||
}
|
||||
|
||||
void TTFReader::Post::Serialize(TTFStream& s)
|
||||
{
|
||||
reserved = 0;
|
||||
s % format % italicAngle % underlinePosition % underlineThickness % isFixedPitch
|
||||
% reserved % minMemType42 % maxMemType42 % minMemType1 % maxMemType1;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
207
uppsrc/PdfDraw/TTFSubset.cpp
Normal file
207
uppsrc/PdfDraw/TTFSubset.cpp
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
#include "PdfDraw.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
dword sCheckSum(const String& data)
|
||||
{
|
||||
const byte *s = (byte *)~data;
|
||||
const byte *lim = s + (data.GetCount() & ~3);
|
||||
dword sum = 0;
|
||||
while(s < lim) {
|
||||
sum += (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3];
|
||||
s += 4;
|
||||
}
|
||||
byte h[4];
|
||||
h[0] = h[1] = h[2] = h[3] = 0;
|
||||
byte *t = h;
|
||||
while(s < (byte *)data.End())
|
||||
*t++ = *s++;
|
||||
sum += (h[0] << 24) | (h[1] << 16) | (h[2] << 8) | h[3];
|
||||
return sum;
|
||||
}
|
||||
|
||||
void TTFReader::Set(NewTable& m, const String& data)
|
||||
{
|
||||
m.data = data;
|
||||
m.checksum = sCheckSum(data);
|
||||
}
|
||||
|
||||
void TTFReader::Add(Array<NewTable>& t, const char *name, const String& data)
|
||||
{
|
||||
if(IsNull(data))
|
||||
return;
|
||||
NewTable& m = t.Add();
|
||||
m.name = name;
|
||||
ASSERT(m.name.GetCount() == 4);
|
||||
Set(m, data);
|
||||
m.checksum = sCheckSum(m.data);
|
||||
}
|
||||
|
||||
String TTFReader::CreateHeader(const Array<NewTable>& t)
|
||||
{
|
||||
TTFStreamOut out;
|
||||
int i = 1;
|
||||
int k = 0;
|
||||
while(i <= t.GetCount()) {
|
||||
i <<= 1;
|
||||
k++;
|
||||
}
|
||||
out.Put32(0x00010000);
|
||||
out.Put16(t.GetCount());
|
||||
out.Put16(i << 3);
|
||||
out.Put16(k - 1);
|
||||
out.Put16((t.GetCount() << 4) - (i << 3));
|
||||
int offset = 16 * t.GetCount() + 12;
|
||||
for(int i = 0; i < t.GetCount(); i++) {
|
||||
const NewTable& m = t[i];
|
||||
out.Put(m.name);
|
||||
out.Put32(m.checksum);
|
||||
out.Put32(offset);
|
||||
out.Put32(m.data.GetLength());
|
||||
offset += (m.data.GetLength() + 3) & ~3;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
String TTFReader::Subset(const Vector<wchar>& chars, int first, bool os2)
|
||||
{
|
||||
try {
|
||||
ASSERT(chars.GetCount() + first < 256);
|
||||
|
||||
TTFStreamOut cmap;
|
||||
cmap.Put16(0);
|
||||
cmap.Put16(1);
|
||||
cmap.Put16(1);
|
||||
cmap.Put16(0);
|
||||
cmap.Put32(cmap.out.GetLength() + 4);
|
||||
cmap.Put16(0);
|
||||
cmap.Put16(262);
|
||||
cmap.Put16(0);
|
||||
|
||||
Index<int> glyph;
|
||||
glyph.Add(0);
|
||||
for(int i = 0; i < first; i++)
|
||||
cmap.Put8(0);
|
||||
for(int i = 0; i < chars.GetCount(); i++) {
|
||||
int q = GetGlyph(chars[i]);
|
||||
if(q) {
|
||||
cmap.Put8(glyph.GetCount());
|
||||
glyph.Add(q);
|
||||
}
|
||||
else
|
||||
cmap.Put8(0);
|
||||
}
|
||||
for(int i = chars.GetCount(); i < 256; i++)
|
||||
cmap.Put8(0);
|
||||
|
||||
TTFStreamOut loca;
|
||||
TTFStreamIn in;
|
||||
TTFStreamOut glyf;
|
||||
TTFStreamOut hmtx;
|
||||
Seek("glyf", in);
|
||||
for(int i = 0; i < glyph.GetCount(); i++) {
|
||||
int gi = glyph[i];
|
||||
if(gi >= glyphinfo.GetCount())
|
||||
throw Fail();
|
||||
const GlyphInfo &gf = glyphinfo[gi];
|
||||
loca.Put32(glyf.out.GetLength());
|
||||
hmtx.Put16(gf.advanceWidth);
|
||||
hmtx.Put16(gf.leftSideBearing);
|
||||
if(gf.size) {
|
||||
if(gf.size < 10)
|
||||
Error();
|
||||
in.Seek(gf.offset);
|
||||
int c = (int16)Copy16(glyf, in);
|
||||
Copy(glyf, in, 8);
|
||||
if(c < 0) {
|
||||
int flags;
|
||||
do {
|
||||
flags = Copy16(glyf, in);
|
||||
glyf.Put16(glyph.FindAdd(in.Get16()));
|
||||
if(flags & ARG_1_AND_2_ARE_WORDS)
|
||||
Copy(glyf, in, 4);
|
||||
else
|
||||
Copy(glyf, in, 2);
|
||||
if(flags & WE_HAVE_A_SCALE)
|
||||
Copy16(glyf, in);
|
||||
else
|
||||
if(flags & WE_HAVE_AN_X_AND_Y_SCALE)
|
||||
Copy(glyf, in, 4);
|
||||
else
|
||||
if(flags & WE_HAVE_A_TWO_BY_TWO)
|
||||
Copy(glyf, in, 8);
|
||||
}
|
||||
while(flags & MORE_COMPONENTS);
|
||||
if(flags & WE_HAVE_INSTRUCTIONS)
|
||||
Copy(glyf, in, Copy16(glyf, in));
|
||||
}
|
||||
else
|
||||
Copy(glyf, in, gf.size - 10);
|
||||
}
|
||||
}
|
||||
loca.Put32(glyf.out.GetLength());
|
||||
|
||||
Hhea nhhea = hhea;
|
||||
nhhea.numOfLongHorMetrics = glyph.GetCount();
|
||||
TTFStreamOut hhea;
|
||||
nhhea.Serialize(hhea);
|
||||
|
||||
Maxp nmaxp = maxp;
|
||||
nmaxp.numGlyphs = glyph.GetCount();
|
||||
TTFStreamOut maxp;
|
||||
nmaxp.Serialize(maxp);
|
||||
|
||||
Post npost = post;
|
||||
npost.format = 0x00030000;
|
||||
TTFStreamOut post;
|
||||
npost.Serialize(post);
|
||||
|
||||
Head nhead = head;
|
||||
nhead.checkSumAdjustment = 0;
|
||||
nhead.indexToLocFormat = 1;
|
||||
TTFStreamOut head;
|
||||
nhead.Serialize(head);
|
||||
|
||||
Array<NewTable> tab;
|
||||
if(os2)
|
||||
Add(tab, "OS/2", GetTable("OS/2"));
|
||||
Add(tab, "cmap", cmap);
|
||||
Add(tab, "cvt ", GetTable("cvt "));
|
||||
Add(tab, "fpgm", GetTable("fpgm"));
|
||||
Add(tab, "glyf", glyf);
|
||||
int headi = tab.GetCount();
|
||||
Add(tab, "head", head);
|
||||
Add(tab, "hhea", hhea);
|
||||
Add(tab, "hmtx", hmtx);
|
||||
Add(tab, "loca", loca);
|
||||
Add(tab, "maxp", maxp);
|
||||
Add(tab, "name", GetTable("name"));
|
||||
Add(tab, "post", post);
|
||||
Add(tab, "prep", GetTable("prep"));
|
||||
|
||||
dword chksum = sCheckSum(CreateHeader(tab));
|
||||
for(int i = 0; i < tab.GetCount(); i++)
|
||||
chksum += tab[i].checksum;
|
||||
|
||||
nhead.checkSumAdjustment = 0xB1B0AFBA - chksum;
|
||||
head.out.Clear();
|
||||
nhead.Serialize(head);
|
||||
Set(tab[headi], head);
|
||||
|
||||
String result = CreateHeader(tab);
|
||||
for(int i = 0; i < tab.GetCount(); i++) {
|
||||
result.Cat(tab[i].data);
|
||||
result.Cat(0, (4 - result.GetCount()) & 3);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
catch(Fail) {
|
||||
return String::GetVoid();
|
||||
}
|
||||
catch(TTFStream::Fail) {
|
||||
return String::GetVoid();
|
||||
}
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
7
uppsrc/PdfDraw/init
Normal file
7
uppsrc/PdfDraw/init
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef _PdfDraw_icpp_init_stub
|
||||
#define _PdfDraw_icpp_init_stub
|
||||
#include "Draw/init"
|
||||
#define BLITZ_INDEX__ F2EB858D15FF91342F7F9648AA934C9C8
|
||||
#include "PdfReport.icpp"
|
||||
#undef BLITZ_INDEX__
|
||||
#endif
|
||||
6
uppsrc/PdfDraw/ttf.h
Normal file
6
uppsrc/PdfDraw/ttf.h
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _PDF_ttf_h_
|
||||
#define _PDF_ttf_h_
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue