/* * PostScript driver Type1 font functions * * Copyright 2002 Huw D M Davies for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include "wine/port.h" #include #include #include #include #include #include "windef.h" #include "winbase.h" #include "winerror.h" #include "wingdi.h" #include "winspool.h" #include "psdrv.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(psdrv); struct tagTYPE1 { DWORD glyph_sent_size; BOOL *glyph_sent; DWORD emsize; }; #define GLYPH_SENT_INC 128 /* Type 1 font commands */ enum t1_cmds { rlineto = 5, rrcurveto = 8, closepath = 9, hsbw = 13, endchar = 14, rmoveto = 21 }; TYPE1 *T1_download_header(PSDRV_PDEVICE *physDev, char *ps_name, RECT *bbox, UINT emsize) { char *buf; TYPE1 *t1; char dict[] = /* name, emsquare, fontbbox */ "25 dict begin\n" " /FontName /%s def\n" " /Encoding 256 array 0 1 255{1 index exch /.notdef put} for def\n" " /PaintType 0 def\n" " /FontMatrix [1 %d div 0 0 1 %d div 0 0] def\n" " /FontBBox [%d %d %d %d] def\n" " /FontType 1 def\n" " /Private 7 dict begin\n" " /RD {string currentfile exch readhexstring pop} def\n" " /ND {def} def\n" " /NP {put} def\n" " /MinFeature {16 16} def\n" " /BlueValues [] def\n" " /password 5839 def\n" " /lenIV -1 def\n" " currentdict end def\n" " currentdict dup /Private get begin\n" " /CharStrings 256 dict begin\n" " /.notdef 4 RD 8b8b0d0e ND\n" " currentdict end put\n" " end\n" "currentdict end dup /FontName get exch definefont pop\n"; t1 = HeapAlloc(GetProcessHeap(), 0, sizeof(*t1)); t1->emsize = emsize; t1->glyph_sent_size = GLYPH_SENT_INC; t1->glyph_sent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, t1->glyph_sent_size * sizeof(*(t1->glyph_sent))); buf = HeapAlloc(GetProcessHeap(), 0, sizeof(dict) + strlen(ps_name) + 100); sprintf(buf, dict, ps_name, t1->emsize, t1->emsize, bbox->left, bbox->bottom, bbox->right, bbox->top); PSDRV_WriteSpool(physDev, buf, strlen(buf)); HeapFree(GetProcessHeap(), 0, buf); return t1; } typedef struct { BYTE *str; int len, max_len; } STR; static STR *str_init(int sz) { STR *str = HeapAlloc(GetProcessHeap(), 0, sizeof(*str)); str->max_len = sz; str->str = HeapAlloc(GetProcessHeap(), 0, str->max_len); str->len = 0; return str; } static void str_free(STR *str) { HeapFree(GetProcessHeap(), 0, str->str); HeapFree(GetProcessHeap(), 0, str); } static void str_add_byte(STR *str, BYTE b) { if(str->len == str->max_len) { str->max_len *= 2; str->str = HeapReAlloc(GetProcessHeap(), 0, str->str, str->max_len); } str->str[str->len++] = b; } static void str_add_num(STR *str, int num) { if(num <= 107 && num >= -107) str_add_byte(str, num + 139); else if(num >= 108 && num <= 1131) { str_add_byte(str, ((num - 108) >> 8) + 247); str_add_byte(str, (num - 108) & 0xff); } else if(num <= -108 && num >= -1131) { num = -num; str_add_byte(str, ((num - 108) >> 8) + 251); str_add_byte(str, (num - 108) & 0xff); } else { str_add_byte(str, 0xff); str_add_byte(str, (num >> 24) & 0xff); str_add_byte(str, (num >> 16) & 0xff); str_add_byte(str, (num >> 8) & 0xff); str_add_byte(str, (num & 0xff)); } } static void str_add_point(STR *str, POINTFX *pt, POINT *curpos) { POINT newpos; newpos.x = pt->x.value + ((pt->x.fract >> 15) & 0x1); newpos.y = pt->y.value + ((pt->y.fract >> 15) & 0x1); str_add_num(str, newpos.x - curpos->x); str_add_num(str, newpos.y - curpos->y); *curpos = newpos; } static void str_add_cmd(STR *str, enum t1_cmds cmd) { str_add_byte(str, (BYTE)cmd); } static int str_get_bytes(STR *str, BYTE **b) { *b = str->str; return str->len; } BOOL T1_download_glyph(PSDRV_PDEVICE *physDev, DOWNLOAD *pdl, DWORD index, char *glyph_name) { DWORD len, i; char *buf; TYPE1 *t1; STR *charstring; BYTE *bytes; HFONT old_font, unscaled_font; GLYPHMETRICS gm; char *glyph_buf; POINT curpos; TTPOLYGONHEADER *pph; TTPOLYCURVE *ppc; LOGFONTW lf; RECT rc; char glyph_def_begin[] = "/%s findfont dup\n" "/Private get begin\n" "/CharStrings get begin\n" "/%s %d RD\n"; char glyph_def_end[] = "ND\n" "end end\n"; TRACE("%ld %s\n", index, glyph_name); assert(pdl->type == Type1); t1 = pdl->typeinfo.Type1; if(index < t1->glyph_sent_size) { if(t1->glyph_sent[index]) return TRUE; } else { t1->glyph_sent_size = (index / GLYPH_SENT_INC + 1) * GLYPH_SENT_INC; t1->glyph_sent = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, t1->glyph_sent, t1->glyph_sent_size * sizeof(*(t1->glyph_sent))); } GetObjectW(GetCurrentObject(physDev->hdc, OBJ_FONT), sizeof(lf), &lf); rc.left = rc.right = rc.bottom = 0; rc.top = t1->emsize; DPtoLP(physDev->hdc, (POINT*)&rc, 2); lf.lfHeight = -abs(rc.top - rc.bottom); lf.lfOrientation = lf.lfEscapement = 0; unscaled_font = CreateFontIndirectW(&lf); old_font = SelectObject(physDev->hdc, unscaled_font); len = GetGlyphOutlineW(physDev->hdc, index, GGO_GLYPH_INDEX | GGO_BEZIER, &gm, 0, NULL, NULL); if(len == GDI_ERROR) return FALSE; glyph_buf = HeapAlloc(GetProcessHeap(), 0, len); GetGlyphOutlineW(physDev->hdc, index, GGO_GLYPH_INDEX | GGO_BEZIER, &gm, len, glyph_buf, NULL); SelectObject(physDev->hdc, old_font); DeleteObject(unscaled_font); charstring = str_init(100); curpos.x = gm.gmptGlyphOrigin.x; curpos.y = 0; str_add_num(charstring, curpos.x); str_add_num(charstring, gm.gmCellIncX); str_add_cmd(charstring, hsbw); pph = (TTPOLYGONHEADER*)glyph_buf; while((char*)pph < glyph_buf + len) { TRACE("contour len %ld\n", pph->cb); ppc = (TTPOLYCURVE*)((char*)pph + sizeof(*pph)); str_add_point(charstring, &pph->pfxStart, &curpos); str_add_cmd(charstring, rmoveto); while((char*)ppc < (char*)pph + pph->cb) { TRACE("line type %d cpfx = %d\n", ppc->wType, ppc->cpfx); switch(ppc->wType) { case TT_PRIM_LINE: for(i = 0; i < ppc->cpfx; i++) { str_add_point(charstring, ppc->apfx + i, &curpos); str_add_cmd(charstring, rlineto); } break; case TT_PRIM_CSPLINE: for(i = 0; i < ppc->cpfx/3; i++) { str_add_point(charstring, ppc->apfx + 3 * i, &curpos); str_add_point(charstring, ppc->apfx + 3 * i + 1, &curpos); str_add_point(charstring, ppc->apfx + 3 * i + 2, &curpos); str_add_cmd(charstring, rrcurveto); } break; default: ERR("curve type = %d\n", ppc->wType); return FALSE; } ppc = (TTPOLYCURVE*)((char*)ppc + sizeof(*ppc) + (ppc->cpfx - 1) * sizeof(POINTFX)); } str_add_cmd(charstring, closepath); pph = (TTPOLYGONHEADER*)((char*)pph + pph->cb); } str_add_cmd(charstring, endchar); buf = HeapAlloc(GetProcessHeap(), 0, sizeof(glyph_def_begin) + strlen(pdl->ps_name) + strlen(glyph_name) + 100); sprintf(buf, "%%%%glyph %04lx\n", index); PSDRV_WriteSpool(physDev, buf, strlen(buf)); len = str_get_bytes(charstring, &bytes); sprintf(buf, glyph_def_begin, pdl->ps_name, glyph_name, len); PSDRV_WriteSpool(physDev, buf, strlen(buf)); PSDRV_WriteBytes(physDev, bytes, len); sprintf(buf, glyph_def_end); PSDRV_WriteSpool(physDev, buf, strlen(buf)); str_free(charstring); t1->glyph_sent[index] = TRUE; HeapFree(GetProcessHeap(), 0, glyph_buf); HeapFree(GetProcessHeap(), 0, buf); return TRUE; } void T1_free(TYPE1 *t1) { HeapFree(GetProcessHeap(), 0, t1->glyph_sent); HeapFree(GetProcessHeap(), 0, t1); return; }