diff --git a/dlls/wineps/Makefile.in b/dlls/wineps/Makefile.in index 5c5b7d773b2..5ce0d51c84e 100644 --- a/dlls/wineps/Makefile.in +++ b/dlls/wineps/Makefile.in @@ -57,8 +57,10 @@ C_SRCS = \ bitblt.c \ bitmap.c \ brush.c \ + builtin.c \ clipping.c \ color.c \ + download.c \ driver.c \ escape.c \ font.c \ @@ -71,7 +73,9 @@ C_SRCS = \ ps.c \ text.c \ truetype.c \ + type1.c \ type1afm.c \ + type42.c \ $(DATA_C_SRCS) RC_SRCS= rsrc.rc diff --git a/dlls/wineps/brush.c b/dlls/wineps/brush.c index d5e522cc29a..536010f67c5 100644 --- a/dlls/wineps/brush.c +++ b/dlls/wineps/brush.c @@ -49,7 +49,7 @@ HBRUSH PSDRV_SelectBrush( PSDRV_PDEVICE *physDev, HBRUSH hbrush ) break; case BS_PATTERN: - FIXME("Unsupported brush style %d\n", logbrush.lbStyle); + case BS_DIBPATTERN: break; default: @@ -226,13 +226,28 @@ BOOL PSDRV_Brush(PSDRV_PDEVICE *physDev, BOOL EO) } break; + case BS_DIBPATTERN: + { + BITMAPINFO *bmi = GlobalLock16(logbrush.lbHatch); + UINT usage = logbrush.lbColor; + TRACE("size %ldx%ldx%d\n", bmi->bmiHeader.biWidth, + bmi->bmiHeader.biHeight, bmi->bmiHeader.biBitCount); + if(physDev->pi->ppd->LanguageLevel > 1) { + PSDRV_WriteGSave(physDev); + ret = PSDRV_WriteDIBPatternDict(physDev, bmi, usage); + PSDRV_Fill(physDev, EO); + PSDRV_WriteGRestore(physDev); + } else { + FIXME("Trying to set a pattern brush on a level 1 printer\n"); + ret = FALSE; + } + GlobalUnlock16(logbrush.lbHatch); + } + break; + default: ret = FALSE; break; } return ret; } - - - - diff --git a/dlls/wineps/builtin.c b/dlls/wineps/builtin.c new file mode 100644 index 00000000000..4b030e52d63 --- /dev/null +++ b/dlls/wineps/builtin.c @@ -0,0 +1,435 @@ +/* + * PostScript driver builtin 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 +#include +#include +#include "winspool.h" +#include "gdi.h" +#include "psdrv.h" +#include "wine/debug.h" +#include "winerror.h" + +WINE_DEFAULT_DEBUG_CHANNEL(psdrv); + + +/*********************************************************************** + * is_stock_font + */ +inline static BOOL is_stock_font( HFONT font ) +{ + int i; + for (i = OEM_FIXED_FONT; i <= DEFAULT_GUI_FONT; i++) + { + if (i != DEFAULT_PALETTE && font == GetStockObject(i)) return TRUE; + } + return FALSE; +} + + +/******************************************************************************* + * ScaleFont + * + * Scale builtin font to requested lfHeight + * + */ +inline static float round(float f) +{ + return (f > 0) ? (f + 0.5) : (f - 0.5); +} + +static VOID ScaleFont(const AFM *afm, LONG lfHeight, PSFONT *font, + TEXTMETRICW *tm) +{ + const WINMETRICS *wm = &(afm->WinMetrics); + USHORT usUnitsPerEm, usWinAscent, usWinDescent; + SHORT sAscender, sDescender, sLineGap, sAvgCharWidth; + + TRACE("'%s' %li\n", afm->FontName, lfHeight); + + if (lfHeight < 0) /* match em height */ + { + font->fontinfo.Builtin.scale = - ((float)lfHeight / (float)(wm->usUnitsPerEm)); + } + else /* match cell height */ + { + font->fontinfo.Builtin.scale = (float)lfHeight / + (float)(wm->usWinAscent + wm->usWinDescent); + } + + font->size = (INT)round(font->fontinfo.Builtin.scale * (float)wm->usUnitsPerEm); + + usUnitsPerEm = (USHORT)round((float)(wm->usUnitsPerEm) * font->fontinfo.Builtin.scale); + sAscender = (SHORT)round((float)(wm->sAscender) * font->fontinfo.Builtin.scale); + sDescender = (SHORT)round((float)(wm->sDescender) * font->fontinfo.Builtin.scale); + sLineGap = (SHORT)round((float)(wm->sLineGap) * font->fontinfo.Builtin.scale); + usWinAscent = (USHORT)round((float)(wm->usWinAscent) * font->fontinfo.Builtin.scale); + usWinDescent = (USHORT)round((float)(wm->usWinDescent) * font->fontinfo.Builtin.scale); + sAvgCharWidth = (SHORT)round((float)(wm->sAvgCharWidth) * font->fontinfo.Builtin.scale); + + tm->tmAscent = (LONG)usWinAscent; + tm->tmDescent = (LONG)usWinDescent; + tm->tmHeight = tm->tmAscent + tm->tmDescent; + + tm->tmInternalLeading = tm->tmHeight - (LONG)usUnitsPerEm; + if (tm->tmInternalLeading < 0) + tm->tmInternalLeading = 0; + + tm->tmExternalLeading = + (LONG)(sAscender - sDescender + sLineGap) - tm->tmHeight; + if (tm->tmExternalLeading < 0) + tm->tmExternalLeading = 0; + + tm->tmAveCharWidth = (LONG)sAvgCharWidth; + + tm->tmWeight = afm->Weight; + tm->tmItalic = (afm->ItalicAngle != 0.0); + tm->tmUnderlined = 0; + tm->tmStruckOut = 0; + tm->tmFirstChar = (WCHAR)(afm->Metrics[0].UV); + tm->tmLastChar = (WCHAR)(afm->Metrics[afm->NumofMetrics - 1].UV); + tm->tmDefaultChar = 0x001f; /* Win2K does this - FIXME? */ + tm->tmBreakChar = tm->tmFirstChar; /* should be 'space' */ + + tm->tmPitchAndFamily = TMPF_DEVICE | TMPF_VECTOR; + if (!afm->IsFixedPitch) + tm->tmPitchAndFamily |= TMPF_FIXED_PITCH; /* yes, it's backwards */ + if (wm->usUnitsPerEm != 1000) + tm->tmPitchAndFamily |= TMPF_TRUETYPE; + + tm->tmCharSet = ANSI_CHARSET; /* FIXME */ + tm->tmOverhang = 0; + + /* + * This is kludgy. font->scale is used in several places in the driver + * to adjust PostScript-style metrics. Since these metrics have been + * "normalized" to an em-square size of 1000, font->scale needs to be + * similarly adjusted.. + */ + + font->fontinfo.Builtin.scale *= (float)wm->usUnitsPerEm / 1000.0; + + tm->tmMaxCharWidth = (LONG)round( + (afm->FontBBox.urx - afm->FontBBox.llx) * font->fontinfo.Builtin.scale); + + font->underlinePosition = afm->UnderlinePosition * font->fontinfo.Builtin.scale; + font->underlineThickness = afm->UnderlineThickness * font->fontinfo.Builtin.scale; + font->strikeoutPosition = tm->tmAscent / 2; + font->strikeoutThickness = font->underlineThickness; + + TRACE("Selected PS font '%s' size %d weight %ld.\n", afm->FontName, + font->size, tm->tmWeight ); + TRACE("H = %ld As = %ld Des = %ld IL = %ld EL = %ld\n", tm->tmHeight, + tm->tmAscent, tm->tmDescent, tm->tmInternalLeading, + tm->tmExternalLeading); +} + + +/**************************************************************************** + * PSDRV_SelectBuiltinFont + * + * Set up physDev->font for a builtin font + * + */ +BOOL PSDRV_SelectBuiltinFont(PSDRV_PDEVICE *physDev, HFONT hfont, + LOGFONTW *plf, LPSTR FaceName) +{ + AFMLISTENTRY *afmle; + FONTFAMILY *family; + BOOL bd = FALSE, it = FALSE; + LONG height; + + TRACE("Trying to find facename '%s'\n", FaceName); + + /* Look for a matching font family */ + for(family = physDev->pi->Fonts; family; family = family->next) { + if(!strcasecmp(FaceName, family->FamilyName)) + break; + } + + if(!family) { + /* Fallback for Window's font families to common PostScript families */ + if(!strcmp(FaceName, "Arial")) + strcpy(FaceName, "Helvetica"); + else if(!strcmp(FaceName, "System")) + strcpy(FaceName, "Helvetica"); + else if(!strcmp(FaceName, "Times New Roman")) + strcpy(FaceName, "Times"); + else if(!strcmp(FaceName, "Courier New")) + strcpy(FaceName, "Courier"); + + for(family = physDev->pi->Fonts; family; family = family->next) { + if(!strcmp(FaceName, family->FamilyName)) + break; + } + } + /* If all else fails, use the first font defined for the printer */ + if(!family) + family = physDev->pi->Fonts; + + TRACE("Got family '%s'\n", family->FamilyName); + + if(plf->lfItalic) + it = TRUE; + if(plf->lfWeight > 550) + bd = TRUE; + + for(afmle = family->afmlist; afmle; afmle = afmle->next) { + if( (bd == (afmle->afm->Weight == FW_BOLD)) && + (it == (afmle->afm->ItalicAngle != 0.0)) ) + break; + } + if(!afmle) + afmle = family->afmlist; /* not ideal */ + + TRACE("Got font '%s'\n", afmle->afm->FontName); + + physDev->font.fontloc = Builtin; + physDev->font.fontinfo.Builtin.afm = afmle->afm; + + height = plf->lfHeight; + /* stock fonts ignore the mapping mode */ + if (!is_stock_font( hfont )) { + POINT pts[2]; + pts[0].x = pts[0].y = pts[1].x = 0; + pts[1].y = height; + LPtoDP(physDev->hdc, pts, 2); + height = pts[1].y - pts[0].y; + } + ScaleFont(physDev->font.fontinfo.Builtin.afm, height, + &(physDev->font), &(physDev->font.fontinfo.Builtin.tm)); + + + /* Does anyone know if these are supposed to be reversed like this? */ + + physDev->font.fontinfo.Builtin.tm.tmDigitizedAspectX = physDev->logPixelsY; + physDev->font.fontinfo.Builtin.tm.tmDigitizedAspectY = physDev->logPixelsX; + + return TRUE; +} + +BOOL PSDRV_WriteSetBuiltinFont(PSDRV_PDEVICE *physDev) +{ + return PSDRV_WriteSetFont(physDev, + physDev->font.fontinfo.Builtin.afm->FontName, + physDev->font.size, physDev->font.escapement); +} + +BOOL PSDRV_WriteBuiltinGlyphShow(PSDRV_PDEVICE *physDev, LPCWSTR str, INT count) +{ + int i; + LPCSTR name; + + for (i = 0; i < count; ++i) + { + name = PSDRV_UVMetrics(str[i], physDev->font.fontinfo.Builtin.afm)->N->sz; + + PSDRV_WriteGlyphShow(physDev, name); + } + + return TRUE; +} + +/*********************************************************************** + * PSDRV_GetTextMetrics + */ +BOOL PSDRV_GetTextMetrics(PSDRV_PDEVICE *physDev, TEXTMETRICW *metrics) +{ + assert(physDev->dc->gdiFont == 0); + assert(physDev->font.fontloc == Builtin); + + memcpy(metrics, &(physDev->font.fontinfo.Builtin.tm), + sizeof(physDev->font.fontinfo.Builtin.tm)); + return TRUE; +} + +/****************************************************************************** + * PSDRV_UVMetrics + * + * Find the AFMMETRICS for a given UV. Returns first glyph in the font + * (space?) if the font does not have a glyph for the given UV. + */ +static int MetricsByUV(const void *a, const void *b) +{ + return (int)(((const AFMMETRICS *)a)->UV - ((const AFMMETRICS *)b)->UV); +} + +const AFMMETRICS *PSDRV_UVMetrics(LONG UV, const AFM *afm) +{ + AFMMETRICS key; + const AFMMETRICS *needle; + + /* + * Ugly work-around for symbol fonts. Wine is sending characters which + * belong in the Unicode private use range (U+F020 - U+F0FF) as ASCII + * characters (U+0020 - U+00FF). + */ + + if ((afm->Metrics->UV & 0xff00) == 0xf000 && UV < 0x100) + UV |= 0xf000; + + key.UV = UV; + + needle = bsearch(&key, afm->Metrics, afm->NumofMetrics, sizeof(AFMMETRICS), + MetricsByUV); + + if (needle == NULL) + { + WARN("No glyph for U+%.4lX in %s\n", UV, afm->FontName); + needle = afm->Metrics; + } + + return needle; +} + +/*********************************************************************** + * PSDRV_GetTextExtentPoint + */ +BOOL PSDRV_GetTextExtentPoint(PSDRV_PDEVICE *physDev, LPCWSTR str, INT count, LPSIZE size) +{ + int i; + float width = 0.0; + + assert(physDev->dc->gdiFont == 0); + assert(physDev->font.fontloc == Builtin); + + TRACE("%s %i\n", debugstr_wn(str, count), count); + + for (i = 0; i < count && str[i] != '\0'; ++i) + width += PSDRV_UVMetrics(str[i], physDev->font.fontinfo.Builtin.afm)->WX; + + width *= physDev->font.fontinfo.Builtin.scale; + + size->cx = GDI_ROUND((FLOAT)width * physDev->dc->xformVport2World.eM11); + size->cy = GDI_ROUND((FLOAT)physDev->font.fontinfo.Builtin.tm.tmHeight * + physDev->dc->xformVport2World.eM22); + + TRACE("cx=%li cy=%li\n", size->cx, size->cy); + + return TRUE; +} + +/*********************************************************************** + * PSDRV_GetCharWidth + */ +BOOL PSDRV_GetCharWidth(PSDRV_PDEVICE *physDev, UINT firstChar, UINT lastChar, LPINT buffer) +{ + UINT i; + + assert(physDev->dc->gdiFont == 0); + assert(physDev->font.fontloc == Builtin); + + TRACE("U+%.4X U+%.4X\n", firstChar, lastChar); + + if (lastChar > 0xffff || firstChar > lastChar) + { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + for (i = firstChar; i <= lastChar; ++i) + { + *buffer = GDI_ROUND(PSDRV_UVMetrics(i, physDev->font.fontinfo.Builtin.afm)->WX + * physDev->font.fontinfo.Builtin.scale); + TRACE("U+%.4X: %i\n", i, *buffer); + ++buffer; + } + + return TRUE; +} + + +/*********************************************************************** + * PSDRV_GetFontMetric + */ +static UINT PSDRV_GetFontMetric(HDC hdc, const AFM *afm, + NEWTEXTMETRICEXW *ntmx, ENUMLOGFONTEXW *elfx) +{ + /* ntmx->ntmTm is NEWTEXTMETRICW; compatible w/ TEXTMETRICW per Win32 doc */ + + TEXTMETRICW *tm = (TEXTMETRICW *)&(ntmx->ntmTm); + LOGFONTW *lf = &(elfx->elfLogFont); + PSFONT font; + + memset(ntmx, 0, sizeof(*ntmx)); + memset(elfx, 0, sizeof(*elfx)); + + ScaleFont(afm, -(LONG)(afm->WinMetrics.usUnitsPerEm), &font, tm); + + lf->lfHeight = tm->tmHeight; + lf->lfWidth = tm->tmAveCharWidth; + lf->lfWeight = tm->tmWeight; + lf->lfItalic = tm->tmItalic; + lf->lfCharSet = tm->tmCharSet; + + lf->lfPitchAndFamily = (afm->IsFixedPitch) ? FIXED_PITCH : VARIABLE_PITCH; + + MultiByteToWideChar(CP_ACP, 0, afm->FamilyName, -1, lf->lfFaceName, + LF_FACESIZE); + + return DEVICE_FONTTYPE; +} + +/*********************************************************************** + * PSDRV_EnumDeviceFonts + */ +BOOL PSDRV_EnumDeviceFonts( PSDRV_PDEVICE *physDev, LPLOGFONTW plf, + DEVICEFONTENUMPROC proc, LPARAM lp ) +{ + ENUMLOGFONTEXW lf; + NEWTEXTMETRICEXW tm; + BOOL b, bRet = 0; + AFMLISTENTRY *afmle; + FONTFAMILY *family; + char FaceName[LF_FACESIZE]; + + if( plf->lfFaceName[0] ) { + WideCharToMultiByte(CP_ACP, 0, plf->lfFaceName, -1, + FaceName, sizeof(FaceName), NULL, NULL); + TRACE("lfFaceName = '%s'\n", FaceName); + for(family = physDev->pi->Fonts; family; family = family->next) { + if(!strncmp(FaceName, family->FamilyName, + strlen(family->FamilyName))) + break; + } + if(family) { + for(afmle = family->afmlist; afmle; afmle = afmle->next) { + TRACE("Got '%s'\n", afmle->afm->FontName); + if( (b = (*proc)( &lf, &tm, + PSDRV_GetFontMetric( physDev->hdc, afmle->afm, &tm, &lf ), + lp )) ) + bRet = b; + else break; + } + } + } else { + + TRACE("lfFaceName = NULL\n"); + for(family = physDev->pi->Fonts; family; family = family->next) { + afmle = family->afmlist; + TRACE("Got '%s'\n", afmle->afm->FontName); + if( (b = (*proc)( &lf, &tm, + PSDRV_GetFontMetric( physDev->hdc, afmle->afm, &tm, &lf ), + lp )) ) + bRet = b; + else break; + } + } + return bRet; +} diff --git a/dlls/wineps/download.c b/dlls/wineps/download.c new file mode 100644 index 00000000000..6af40a62c6f --- /dev/null +++ b/dlls/wineps/download.c @@ -0,0 +1,231 @@ +/* + * PostScript driver downloadable 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 +#include +#include +#include +#include "winspool.h" +#include "gdi.h" +#include "psdrv.h" +#include "wine/debug.h" +#include "winerror.h" + +WINE_DEFAULT_DEBUG_CHANNEL(psdrv); + + +/**************************************************************************** + * get_download_name + */ +static void get_download_name(PSDRV_PDEVICE *physDev, LPOUTLINETEXTMETRICA + potm, char **str) +{ + int len; + char *p; + len = strlen((char*)potm + (ptrdiff_t)potm->otmpFullName) + 1; + *str = HeapAlloc(GetProcessHeap(),0,len); + strcpy(*str, (char*)potm + (ptrdiff_t)potm->otmpFullName); + + p = *str; + while((p = strchr(p, ' '))) + *p = '_'; + + return; +} + +/**************************************************************************** + * is_font_downloaded + */ +static DOWNLOAD *is_font_downloaded(PSDRV_PDEVICE *physDev, char *ps_name) +{ + DOWNLOAD *pdl; + + for(pdl = physDev->downloaded_fonts; pdl; pdl = pdl->next) + if(!strcmp(pdl->ps_name, ps_name)) + break; + return pdl; +} + +/**************************************************************************** + * PSDRV_SelectDownloadFont + * + * Set up physDev->font for a downloadable font + * + */ +BOOL PSDRV_SelectDownloadFont(PSDRV_PDEVICE *physDev) +{ + char *ps_name; + LPOUTLINETEXTMETRICA potm; + DWORD len = GetOutlineTextMetricsA(physDev->hdc, 0, NULL); + + potm = HeapAlloc(GetProcessHeap(), 0, len); + GetOutlineTextMetricsA(physDev->hdc, len, potm); + get_download_name(physDev, potm, &ps_name); + + physDev->font.fontloc = Download; + physDev->font.fontinfo.Download = is_font_downloaded(physDev, ps_name); + + physDev->font.size = INTERNAL_YWSTODS(physDev->dc, /* ppem */ + potm->otmTextMetrics.tmAscent + + potm->otmTextMetrics.tmDescent - + potm->otmTextMetrics.tmInternalLeading); + physDev->font.underlineThickness = potm->otmsUnderscoreSize; + physDev->font.underlinePosition = potm->otmsUnderscorePosition; + physDev->font.strikeoutThickness = potm->otmsStrikeoutSize; + physDev->font.strikeoutPosition = potm->otmsStrikeoutPosition; + + HeapFree(GetProcessHeap(), 0, ps_name); + HeapFree(GetProcessHeap(), 0, potm); + return TRUE; +} + +/**************************************************************************** + * PSDRV_WriteSetDownloadFont + * + * Write setfont for download font. + * + */ +BOOL PSDRV_WriteSetDownloadFont(PSDRV_PDEVICE *physDev) +{ + char *ps_name; + LPOUTLINETEXTMETRICA potm; + DWORD len = GetOutlineTextMetricsA(physDev->hdc, 0, NULL); + DOWNLOAD *pdl; + + assert(physDev->font.fontloc == Download); + + potm = HeapAlloc(GetProcessHeap(), 0, len); + GetOutlineTextMetricsA(physDev->hdc, len, potm); + + get_download_name(physDev, potm, &ps_name); + + if(physDev->font.fontinfo.Download == NULL) { + pdl = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pdl)); + pdl->ps_name = HeapAlloc(GetProcessHeap(), 0, strlen(ps_name)+1); + strcpy(pdl->ps_name, ps_name); + pdl->next = NULL; + + if(physDev->pi->ppd->TTRasterizer == RO_Type42) { + pdl->typeinfo.Type42 = T42_download_header(physDev, potm, + ps_name); + pdl->type = Type42; + } else { + pdl->typeinfo.Type1 = T1_download_header(physDev, potm, ps_name); + pdl->type = Type1; + } + if(pdl) { + pdl->next = physDev->downloaded_fonts; + physDev->downloaded_fonts = pdl; + } + physDev->font.fontinfo.Download = pdl; + } + + + PSDRV_WriteSetFont(physDev, ps_name, physDev->font.size, + physDev->font.escapement); + + HeapFree(GetProcessHeap(), 0, ps_name); + HeapFree(GetProcessHeap(), 0, potm); + return TRUE; +} + +void get_glyph_name(HDC hdc, WORD index, char *name) +{ + /* FIXME */ + sprintf(name, "g%04x", index); + return; +} + +/**************************************************************************** + * PSDRV_WriteDownloadGlyphShow + * + * Download and write out a number of glyphs + * + */ +BOOL PSDRV_WriteDownloadGlyphShow(PSDRV_PDEVICE *physDev, WORD *glyphs, + UINT count) +{ + UINT i; + char g_name[MAX_G_NAME + 1]; + assert(physDev->font.fontloc == Download); + + switch(physDev->font.fontinfo.Download->type) { + case Type42: + for(i = 0; i < count; i++) { + get_glyph_name(physDev->hdc, glyphs[i], g_name); + T42_download_glyph(physDev, physDev->font.fontinfo.Download, + glyphs[i], g_name); + PSDRV_WriteGlyphShow(physDev, g_name); + } + break; + + case Type1: + for(i = 0; i < count; i++) { + get_glyph_name(physDev->hdc, glyphs[i], g_name); + T1_download_glyph(physDev, physDev->font.fontinfo.Download, + glyphs[i], g_name); + PSDRV_WriteGlyphShow(physDev, g_name); + } + break; + + default: + ERR("Type = %d\n", physDev->font.fontinfo.Download->type); + assert(0); + } + return TRUE; +} + +/**************************************************************************** + * PSDRV_EmptyDownloadList + * + * Clear the list of downloaded fonts + * + */ +BOOL PSDRV_EmptyDownloadList(PSDRV_PDEVICE *physDev) +{ + DOWNLOAD *pdl, *old; + if(physDev->font.fontloc == Download) { + physDev->font.set = FALSE; + physDev->font.fontinfo.Download = NULL; + } + + pdl = physDev->downloaded_fonts; + physDev->downloaded_fonts = NULL; + while(pdl) { + switch(pdl->type) { + case Type42: + T42_free(pdl->typeinfo.Type42); + break; + + case Type1: + T1_free(pdl->typeinfo.Type1); + break; + + default: + ERR("Type = %d\n", pdl->type); + assert(0); + } + + HeapFree(GetProcessHeap(), 0, pdl->ps_name); + old = pdl; + pdl = pdl->next; + HeapFree(GetProcessHeap(), 0, old); + } + return TRUE; +} diff --git a/dlls/wineps/driver.c b/dlls/wineps/driver.c index 4d7a717b355..6c0acf23517 100644 --- a/dlls/wineps/driver.c +++ b/dlls/wineps/driver.c @@ -335,7 +335,10 @@ fwMode); FIXME("Mode DM_UPDATE. Just do the same as DM_COPY\n"); if((fwMode & DM_COPY) || (fwMode & DM_UPDATE)) { - memcpy(lpdmOutput, pi->Devmode, sizeof(DEVMODEA)); + if (lpdmOutput) + memcpy(lpdmOutput, pi->Devmode, sizeof(DEVMODEA)); + else + FIXME("lpdmOutput is NULL what should we do??\n"); } return IDOK; } diff --git a/dlls/wineps/escape.c b/dlls/wineps/escape.c index 01ce614b255..9d0cd569482 100644 --- a/dlls/wineps/escape.c +++ b/dlls/wineps/escape.c @@ -246,6 +246,7 @@ INT PSDRV_EndPage( PSDRV_PDEVICE *physDev ) } if(!PSDRV_WriteEndPage( physDev )) return 0; + PSDRV_EmptyDownloadList(physDev); physDev->job.OutOfPage = TRUE; return 1; } diff --git a/dlls/wineps/font.c b/dlls/wineps/font.c index 91e5efe8e2e..3c0e4b1b369 100644 --- a/dlls/wineps/font.c +++ b/dlls/wineps/font.c @@ -18,135 +18,22 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include -#include /* for bsearch() */ +#include +#include #include "winspool.h" #include "gdi.h" #include "psdrv.h" #include "wine/debug.h" -#include "winerror.h" WINE_DEFAULT_DEBUG_CHANNEL(psdrv); -/*********************************************************************** - * is_stock_font - */ -inline static BOOL is_stock_font( HFONT font ) -{ - int i; - for (i = OEM_FIXED_FONT; i <= DEFAULT_GUI_FONT; i++) - { - if (i != DEFAULT_PALETTE && font == GetStockObject(i)) return TRUE; - } - return FALSE; -} - - -/******************************************************************************* - * ScaleFont - * - * Scale font to requested lfHeight - * - */ -inline static float round(float f) -{ - return (f > 0) ? (f + 0.5) : (f - 0.5); -} - -static VOID ScaleFont(const AFM *afm, LONG lfHeight, PSFONT *font, - TEXTMETRICW *tm) -{ - const WINMETRICS *wm = &(afm->WinMetrics); - USHORT usUnitsPerEm, usWinAscent, usWinDescent; - SHORT sAscender, sDescender, sLineGap, sTypoAscender; - SHORT sTypoDescender, sTypoLineGap, sAvgCharWidth; - - TRACE("'%s' %li\n", afm->FontName, lfHeight); - - if (lfHeight < 0) /* match em height */ - { - font->scale = - ((float)lfHeight / (float)(wm->usUnitsPerEm)); - } - else /* match cell height */ - { - font->scale = (float)lfHeight / - (float)(wm->usWinAscent + wm->usWinDescent); - } - - font->size = (INT)round(font->scale * (float)wm->usUnitsPerEm); - font->set = FALSE; - - usUnitsPerEm = (USHORT)round((float)(wm->usUnitsPerEm) * font->scale); - sAscender = (SHORT)round((float)(wm->sAscender) * font->scale); - sDescender = (SHORT)round((float)(wm->sDescender) * font->scale); - sLineGap = (SHORT)round((float)(wm->sLineGap) * font->scale); - sTypoAscender = (SHORT)round((float)(wm->sTypoAscender) * font->scale); - sTypoDescender = (SHORT)round((float)(wm->sTypoDescender) * font->scale); - sTypoLineGap = (SHORT)round((float)(wm->sTypoLineGap) * font->scale); - usWinAscent = (USHORT)round((float)(wm->usWinAscent) * font->scale); - usWinDescent = (USHORT)round((float)(wm->usWinDescent) * font->scale); - sAvgCharWidth = (SHORT)round((float)(wm->sAvgCharWidth) * font->scale); - - tm->tmAscent = (LONG)usWinAscent; - tm->tmDescent = (LONG)usWinDescent; - tm->tmHeight = tm->tmAscent + tm->tmDescent; - - tm->tmInternalLeading = tm->tmHeight - (LONG)usUnitsPerEm; - if (tm->tmInternalLeading < 0) - tm->tmInternalLeading = 0; - - tm->tmExternalLeading = - (LONG)(sAscender - sDescender + sLineGap) - tm->tmHeight; - if (tm->tmExternalLeading < 0) - tm->tmExternalLeading = 0; - - tm->tmAveCharWidth = (LONG)sAvgCharWidth; - - tm->tmWeight = afm->Weight; - tm->tmItalic = (afm->ItalicAngle != 0.0); - tm->tmUnderlined = 0; - tm->tmStruckOut = 0; - tm->tmFirstChar = (WCHAR)(afm->Metrics[0].UV); - tm->tmLastChar = (WCHAR)(afm->Metrics[afm->NumofMetrics - 1].UV); - tm->tmDefaultChar = 0x001f; /* Win2K does this - FIXME? */ - tm->tmBreakChar = tm->tmFirstChar; /* should be 'space' */ - - tm->tmPitchAndFamily = TMPF_DEVICE | TMPF_VECTOR; - if (!afm->IsFixedPitch) - tm->tmPitchAndFamily |= TMPF_FIXED_PITCH; /* yes, it's backwards */ - if (wm->usUnitsPerEm != 1000) - tm->tmPitchAndFamily |= TMPF_TRUETYPE; - - tm->tmCharSet = ANSI_CHARSET; /* FIXME */ - tm->tmOverhang = 0; - - /* - * This is kludgy. font->scale is used in several places in the driver - * to adjust PostScript-style metrics. Since these metrics have been - * "normalized" to an em-square size of 1000, font->scale needs to be - * similarly adjusted.. - */ - - font->scale *= (float)wm->usUnitsPerEm / 1000.0; - - tm->tmMaxCharWidth = (LONG)round( - (afm->FontBBox.urx - afm->FontBBox.llx) * font->scale); - - TRACE("Selected PS font '%s' size %d weight %ld.\n", afm->FontName, - font->size, tm->tmWeight ); - TRACE("H = %ld As = %ld Des = %ld IL = %ld EL = %ld\n", tm->tmHeight, - tm->tmAscent, tm->tmDescent, tm->tmInternalLeading, - tm->tmExternalLeading); -} - /*********************************************************************** * SelectFont (WINEPS.@) */ HFONT PSDRV_SelectFont( PSDRV_PDEVICE *physDev, HFONT hfont ) { LOGFONTW lf; - BOOL bd = FALSE, it = FALSE; - AFMLISTENTRY *afmle; - FONTFAMILY *family; + BOOL subst = FALSE; char FaceName[LF_FACESIZE]; if (!GetObjectW( hfont, sizeof(lf), &lf )) return 0; @@ -155,10 +42,6 @@ HFONT PSDRV_SelectFont( PSDRV_PDEVICE *physDev, HFONT hfont ) debugstr_w(lf.lfFaceName), lf.lfHeight, lf.lfItalic, lf.lfWeight); - if(lf.lfItalic) - it = TRUE; - if(lf.lfWeight > 550) - bd = TRUE; WideCharToMultiByte(CP_ACP, 0, lf.lfFaceName, -1, FaceName, sizeof(FaceName), NULL, NULL); @@ -206,8 +89,11 @@ HFONT PSDRV_SelectFont( PSDRV_PDEVICE *physDev, HFONT hfont ) (LPSTR) physDev->pi->FontSubTable[i].pData, FaceName); if (strlen ((LPSTR) physDev->pi->FontSubTable[i].pData) < LF_FACESIZE) + { strcpy (FaceName, (LPSTR) physDev->pi->FontSubTable[i].pData); + subst = TRUE; + } else WARN ("Facename '%s' is too long; ignoring substitution\n", (LPSTR) physDev->pi->FontSubTable[i].pData); @@ -216,158 +102,16 @@ HFONT PSDRV_SelectFont( PSDRV_PDEVICE *physDev, HFONT hfont ) } } - TRACE("Trying to find facename '%s'\n", FaceName); - - /* Look for a matching font family */ - for(family = physDev->pi->Fonts; family; family = family->next) { - if(!strcasecmp(FaceName, family->FamilyName)) - break; - } - if(!family) { - /* Fallback for Window's font families to common PostScript families */ - if(!strcmp(FaceName, "Arial")) - strcpy(FaceName, "Helvetica"); - else if(!strcmp(FaceName, "System")) - strcpy(FaceName, "Helvetica"); - else if(!strcmp(FaceName, "Times New Roman")) - strcpy(FaceName, "Times"); - else if(!strcmp(FaceName, "Courier New")) - strcpy(FaceName, "Courier"); - - for(family = physDev->pi->Fonts; family; family = family->next) { - if(!strcmp(FaceName, family->FamilyName)) - break; - } - } - /* If all else fails, use the first font defined for the printer */ - if(!family) - family = physDev->pi->Fonts; - - TRACE("Got family '%s'\n", family->FamilyName); - - for(afmle = family->afmlist; afmle; afmle = afmle->next) { - if( (bd == (afmle->afm->Weight == FW_BOLD)) && - (it == (afmle->afm->ItalicAngle != 0.0)) ) - break; - } - if(!afmle) - afmle = family->afmlist; /* not ideal */ - - TRACE("Got font '%s'\n", afmle->afm->FontName); - - physDev->font.afm = afmle->afm; - /* stock fonts ignore the mapping mode */ - if (!is_stock_font( hfont )) lf.lfHeight = INTERNAL_YWSTODS(physDev->dc, lf.lfHeight); - ScaleFont(physDev->font.afm, lf.lfHeight, - &(physDev->font), &(physDev->font.tm)); - physDev->font.escapement = lf.lfEscapement; + physDev->font.set = FALSE; - /* Does anyone know if these are supposed to be reversed like this? */ - - physDev->font.tm.tmDigitizedAspectX = physDev->logPixelsY; - physDev->font.tm.tmDigitizedAspectY = physDev->logPixelsX; - - return TRUE; /* We'll use a device font for now */ -} - -/*********************************************************************** - * PSDRV_GetTextMetrics - */ -BOOL PSDRV_GetTextMetrics(PSDRV_PDEVICE *physDev, TEXTMETRICW *metrics) -{ - memcpy(metrics, &(physDev->font.tm), sizeof(physDev->font.tm)); - return TRUE; -} - -/****************************************************************************** - * PSDRV_UVMetrics - * - * Find the AFMMETRICS for a given UV. Returns first glyph in the font - * (space?) if the font does not have a glyph for the given UV. - */ -static int MetricsByUV(const void *a, const void *b) -{ - return (int)(((const AFMMETRICS *)a)->UV - ((const AFMMETRICS *)b)->UV); -} - -const AFMMETRICS *PSDRV_UVMetrics(LONG UV, const AFM *afm) -{ - AFMMETRICS key; - const AFMMETRICS *needle; - - /* - * Ugly work-around for symbol fonts. Wine is sending characters which - * belong in the Unicode private use range (U+F020 - U+F0FF) as ASCII - * characters (U+0020 - U+00FF). - */ - - if ((afm->Metrics->UV & 0xff00) == 0xf000 && UV < 0x100) - UV |= 0xf000; - - key.UV = UV; - - needle = bsearch(&key, afm->Metrics, afm->NumofMetrics, sizeof(AFMMETRICS), - MetricsByUV); - - if (needle == NULL) - { - WARN("No glyph for U+%.4lX in %s\n", UV, afm->FontName); - needle = afm->Metrics; + if(physDev->dc->gdiFont && !subst) { + if(PSDRV_SelectDownloadFont(physDev)) + return FALSE; /* use gdi font */ } - return needle; -} - -/*********************************************************************** - * PSDRV_GetTextExtentPoint - */ -BOOL PSDRV_GetTextExtentPoint(PSDRV_PDEVICE *physDev, LPCWSTR str, INT count, LPSIZE size) -{ - DC *dc = physDev->dc; - int i; - float width = 0.0; - - TRACE("%s %i\n", debugstr_wn(str, count), count); - - for (i = 0; i < count && str[i] != '\0'; ++i) - width += PSDRV_UVMetrics(str[i], physDev->font.afm)->WX; - - width *= physDev->font.scale; - - size->cx = GDI_ROUND((FLOAT)width * dc->xformVport2World.eM11); - size->cy = GDI_ROUND((FLOAT)physDev->font.tm.tmHeight * - dc->xformVport2World.eM22); - - TRACE("cx=%li cy=%li\n", size->cx, size->cy); - - return TRUE; -} - -/*********************************************************************** - * PSDRV_GetCharWidth - */ -BOOL PSDRV_GetCharWidth(PSDRV_PDEVICE *physDev, UINT firstChar, UINT lastChar, LPINT buffer) -{ - UINT i; - - TRACE("U+%.4X U+%.4X\n", firstChar, lastChar); - - if (lastChar > 0xffff || firstChar > lastChar) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - for (i = firstChar; i <= lastChar; ++i) - { - *buffer = GDI_ROUND(PSDRV_UVMetrics(i, physDev->font.afm)->WX - * physDev->font.scale); - TRACE("U+%.4X: %i\n", i, *buffer); - ++buffer; - } - - return TRUE; + PSDRV_SelectBuiltinFont(physDev, hfont, &lf, FaceName); + return TRUE; /* use device font */ } /*********************************************************************** @@ -378,83 +122,18 @@ BOOL PSDRV_SetFont( PSDRV_PDEVICE *physDev ) PSDRV_WriteSetColor(physDev, &physDev->font.color); if(physDev->font.set) return TRUE; - PSDRV_WriteSetFont(physDev); + switch(physDev->font.fontloc) { + case Builtin: + PSDRV_WriteSetBuiltinFont(physDev); + break; + case Download: + PSDRV_WriteSetDownloadFont(physDev); + break; + default: + ERR("fontloc = %d\n", physDev->font.fontloc); + assert(1); + break; + } physDev->font.set = TRUE; return TRUE; } - - -/*********************************************************************** - * PSDRV_GetFontMetric - */ -static UINT PSDRV_GetFontMetric( PSDRV_PDEVICE *physDev, const AFM *afm, - NEWTEXTMETRICEXW *ntmx, ENUMLOGFONTEXW *elfx) -{ - /* ntmx->ntmTm is NEWTEXTMETRICW; compatible w/ TEXTMETRICW per Win32 doc */ - - TEXTMETRICW *tm = (TEXTMETRICW *)&(ntmx->ntmTm); - LOGFONTW *lf = &(elfx->elfLogFont); - PSFONT font; - - memset(ntmx, 0, sizeof(*ntmx)); - memset(elfx, 0, sizeof(*elfx)); - - ScaleFont(afm, -(LONG)(afm->WinMetrics.usUnitsPerEm), &font, tm); - - lf->lfHeight = tm->tmHeight; - lf->lfWidth = tm->tmAveCharWidth; - lf->lfWeight = tm->tmWeight; - lf->lfItalic = tm->tmItalic; - lf->lfCharSet = tm->tmCharSet; - - lf->lfPitchAndFamily = (afm->IsFixedPitch) ? FIXED_PITCH : VARIABLE_PITCH; - - MultiByteToWideChar(CP_ACP, 0, afm->FamilyName, -1, lf->lfFaceName, - LF_FACESIZE); - - return DEVICE_FONTTYPE; -} - -/*********************************************************************** - * PSDRV_EnumDeviceFonts - */ -BOOL PSDRV_EnumDeviceFonts( PSDRV_PDEVICE *physDev, LPLOGFONTW plf, - DEVICEFONTENUMPROC proc, LPARAM lp ) -{ - ENUMLOGFONTEXW lf; - NEWTEXTMETRICEXW tm; - BOOL b, bRet = 0; - AFMLISTENTRY *afmle; - FONTFAMILY *family; - char FaceName[LF_FACESIZE]; - - if( plf->lfFaceName[0] ) { - WideCharToMultiByte(CP_ACP, 0, plf->lfFaceName, -1, - FaceName, sizeof(FaceName), NULL, NULL); - TRACE("lfFaceName = '%s'\n", FaceName); - for(family = physDev->pi->Fonts; family; family = family->next) { - if(!strncmp(FaceName, family->FamilyName, - strlen(family->FamilyName))) - break; - } - if(family) { - for(afmle = family->afmlist; afmle; afmle = afmle->next) { - TRACE("Got '%s'\n", afmle->afm->FontName); - if( (b = proc( &lf, &tm, PSDRV_GetFontMetric(physDev, afmle->afm, &tm, &lf), lp )) ) - bRet = b; - else break; - } - } - } else { - - TRACE("lfFaceName = NULL\n"); - for(family = physDev->pi->Fonts; family; family = family->next) { - afmle = family->afmlist; - TRACE("Got '%s'\n", afmle->afm->FontName); - if( (b = proc( &lf, &tm, PSDRV_GetFontMetric(physDev, afmle->afm, &tm, &lf), lp )) ) - bRet = b; - else break; - } - } - return bRet; -} diff --git a/dlls/wineps/ppd.c b/dlls/wineps/ppd.c index 995d103f330..0d92bd9f1d2 100644 --- a/dlls/wineps/ppd.c +++ b/dlls/wineps/ppd.c @@ -778,6 +778,22 @@ PPD *PSDRV_ParsePPD(char *fname) tuple.value = NULL; } + else if(!strcmp("*TTRasterizer", tuple.key)) { + if(!strcasecmp("None", tuple.value)) + ppd->TTRasterizer = RO_None; + else if(!strcasecmp("Accept68K", tuple.value)) + ppd->TTRasterizer = RO_Accept68K; + else if(!strcasecmp("Type42", tuple.value)) + ppd->TTRasterizer = RO_Type42; + else if(!strcasecmp("TrueImage", tuple.value)) + ppd->TTRasterizer = RO_TrueImage; + else { + FIXME("Unknown option %s for *TTRasterizer\n", + tuple.value); + ppd->TTRasterizer = RO_None; + } + } + if(tuple.key) HeapFree(PSDRV_Heap, 0, tuple.key); if(tuple.option) HeapFree(PSDRV_Heap, 0, tuple.option); if(tuple.value) HeapFree(PSDRV_Heap, 0, tuple.value); diff --git a/dlls/wineps/ps.c b/dlls/wineps/ps.c index f8d46c8a699..b8904e352c6 100644 --- a/dlls/wineps/ps.c +++ b/dlls/wineps/ps.c @@ -21,6 +21,7 @@ #include #include #include +#include "gdi.h" #include "psdrv.h" #include "winspool.h" #include "wine/debug.h" @@ -428,21 +429,20 @@ BOOL PSDRV_WriteArc(PSDRV_PDEVICE *physDev, INT x, INT y, INT w, INT h, double a return PSDRV_WriteSpool(physDev, buf, strlen(buf)); } -BOOL PSDRV_WriteSetFont(PSDRV_PDEVICE *physDev) + +BOOL PSDRV_WriteSetFont(PSDRV_PDEVICE *physDev, const char *name, INT size, INT escapement) { char *buf; - buf = (char *)HeapAlloc( PSDRV_Heap, 0, - sizeof(pssetfont) + strlen(physDev->font.afm->FontName) + 40); + buf = (char *)HeapAlloc( PSDRV_Heap, 0, sizeof(pssetfont) + + strlen(name) + 40); if(!buf) { WARN("HeapAlloc failed\n"); return FALSE; } - sprintf(buf, pssetfont, physDev->font.afm->FontName, - physDev->font.size, -physDev->font.size, - -physDev->font.escapement); + sprintf(buf, pssetfont, name, size, -size, -escapement); PSDRV_WriteSpool(physDev, buf, strlen(buf)); HeapFree(PSDRV_Heap, 0, buf); @@ -487,28 +487,19 @@ BOOL PSDRV_WriteSetPen(PSDRV_PDEVICE *physDev) return TRUE; } -BOOL PSDRV_WriteGlyphShow(PSDRV_PDEVICE *physDev, LPCWSTR str, INT count) +BOOL PSDRV_WriteGlyphShow(PSDRV_PDEVICE *physDev, LPCSTR g_name) { char buf[128]; - int i; + int l; - for (i = 0; i < count; ++i) - { - LPCSTR name; - int l; + l = snprintf(buf, sizeof(buf), psglyphshow, g_name); - name = PSDRV_UVMetrics(str[i], physDev->font.afm)->N->sz; - l = snprintf(buf, sizeof(buf), psglyphshow, name); - - if (l < sizeof(psglyphshow) - 2 || l > sizeof(buf) - 1) - { - WARN("Unusable glyph name '%s' - ignoring\n", name); - continue; - } - - PSDRV_WriteSpool(physDev, buf, l); + if (l < sizeof(psglyphshow) - 2 || l > sizeof(buf) - 1) { + WARN("Unusable glyph name '%s' - ignoring\n", g_name); + return FALSE; } + PSDRV_WriteSpool(physDev, buf, l); return TRUE; } @@ -815,3 +806,51 @@ BOOL PSDRV_WritePatternDict(PSDRV_PDEVICE *physDev, BITMAP *bm, BYTE *bits) HeapFree(PSDRV_Heap, 0, buf); return TRUE; } + +BOOL PSDRV_WriteDIBPatternDict(PSDRV_PDEVICE *physDev, BITMAPINFO *bmi, UINT usage) +{ + char start[] = "<<\n /PaintType 1\n /PatternType 1\n /TilingType 1\n " + "/BBox [0 0 %d %d]\n /XStep %d\n /YStep %d\n /PaintProc {\n begin\n"; + + char end[] = " end\n }\n>>\n matrix makepattern setpattern\n"; + char *buf, *ptr; + BYTE *bits; + INT w, h, x, y, colours; + COLORREF map[2]; + + if(bmi->bmiHeader.biBitCount != 1) { + FIXME("dib depth %d not supported\n", bmi->bmiHeader.biBitCount); + return FALSE; + } + + bits = (char*)bmi + bmi->bmiHeader.biSize; + colours = bmi->bmiHeader.biClrUsed; + if(!colours && bmi->bmiHeader.biBitCount <= 8) + colours = 1 << bmi->bmiHeader.biBitCount; + bits += colours * ((usage == DIB_RGB_COLORS) ? + sizeof(RGBQUAD) : sizeof(WORD)); + + w = bmi->bmiHeader.biWidth & ~0x7; + h = bmi->bmiHeader.biHeight & ~0x7; + + buf = HeapAlloc(PSDRV_Heap, 0, sizeof(start) + 100); + sprintf(buf, start, w, h, w, h); + PSDRV_WriteSpool(physDev, buf, strlen(buf)); + PSDRV_WriteIndexColorSpaceBegin(physDev, 1); + map[0] = physDev->dc->textColor; + map[1] = physDev->dc->backgroundColor; + PSDRV_WriteRGB(physDev, map, 2); + PSDRV_WriteIndexColorSpaceEnd(physDev); + ptr = buf; + for(y = h-1; y >= 0; y--) { + for(x = 0; x < w/8; x++) { + sprintf(ptr, "%02x", *(bits + x/8 + y * + (bmi->bmiHeader.biWidth + 31) / 32 * 4)); + ptr += 2; + } + } + PSDRV_WriteImageDict(physDev, 1, 0, 0, 8, 8, 8, 8, buf); + PSDRV_WriteSpool(physDev, end, sizeof(end) - 1); + HeapFree(PSDRV_Heap, 0, buf); + return TRUE; +} diff --git a/dlls/wineps/psdrv.h b/dlls/wineps/psdrv.h index efa4fe923a0..cf331b0ee60 100644 --- a/dlls/wineps/psdrv.h +++ b/dlls/wineps/psdrv.h @@ -169,6 +169,9 @@ typedef struct _tagINPUTSLOT { struct _tagINPUTSLOT *next; } INPUTSLOT; +typedef enum _RASTERIZEROPTION + {RO_None, RO_Accept68K, RO_Type42, RO_TrueImage} RASTERIZEROPTION; + typedef struct { char *NickName; int LanguageLevel; @@ -184,6 +187,7 @@ typedef struct { OPTION *InstalledOptions; CONSTRAINT *Constraints; INPUTSLOT *InputSlots; + RASTERIZEROPTION TTRasterizer; } PPD; typedef struct { @@ -236,12 +240,50 @@ typedef struct { typedef struct { const AFM *afm; - TEXTMETRICW tm; - INT size; float scale; - INT escapement; + TEXTMETRICW tm; +} BUILTIN; + +typedef struct tagTYPE42 TYPE42; + +typedef struct tagTYPE1 TYPE1; + +enum downloadtype { + Type1, Type42 +}; + +typedef struct _tagDOWNLOAD { + enum downloadtype type; + union { + TYPE1 *Type1; + TYPE42 *Type42; + } typeinfo; + char *ps_name; + struct _tagDOWNLOAD *next; +} DOWNLOAD; + +enum fontloc { + Builtin, Download +}; + +typedef struct { + enum fontloc fontloc; + union { + BUILTIN Builtin; + DOWNLOAD *Download; + } fontinfo; + + int size; PSCOLOR color; BOOL set; /* Have we done a setfont yet */ + + /* These are needed by PSDRV_ExtTextOut */ + int escapement; + int underlineThickness; + int underlinePosition; + int strikeoutThickness; + int strikeoutPosition; + } PSFONT; typedef struct { @@ -269,6 +311,7 @@ typedef struct { HDC hdc; struct tagDC *dc; PSFONT font; /* Current PS font */ + DOWNLOAD *downloaded_fonts; PSPEN pen; PSBRUSH brush; PSCOLOR bkColor; @@ -355,8 +398,9 @@ extern BOOL PSDRV_WriteRectangle(PSDRV_PDEVICE *physDev, INT x, INT y, INT width INT height); extern BOOL PSDRV_WriteRRectangle(PSDRV_PDEVICE *physDev, INT x, INT y, INT width, INT height); -extern BOOL PSDRV_WriteSetFont(PSDRV_PDEVICE *physDev); -extern BOOL PSDRV_WriteGlyphShow(PSDRV_PDEVICE *physDev, LPCWSTR str, INT count); +extern BOOL PSDRV_WriteSetFont(PSDRV_PDEVICE *physDev, const char *name, INT size, + INT escapement); +extern BOOL PSDRV_WriteGlyphShow(PSDRV_PDEVICE *physDev, LPCSTR g_name); extern BOOL PSDRV_WriteSetPen(PSDRV_PDEVICE *physDev); extern BOOL PSDRV_WriteArc(PSDRV_PDEVICE *physDev, INT x, INT y, INT w, INT h, double ang1, double ang2); @@ -387,6 +431,7 @@ extern BOOL PSDRV_WriteDIBits24(PSDRV_PDEVICE *physDev, const BYTE *bits, int nu extern BOOL PSDRV_WriteDIBits32(PSDRV_PDEVICE *physDev, const BYTE *bits, int number); extern int PSDRV_WriteSpool(PSDRV_PDEVICE *physDev, LPSTR lpData, WORD cch); extern BOOL PSDRV_WritePatternDict(PSDRV_PDEVICE *physDev, BITMAP *bm, BYTE *bits); +extern BOOL PSDRV_WriteDIBPatternDict(PSDRV_PDEVICE *physDev, BITMAPINFO *bmi, UINT usage); extern BOOL PSDRV_WriteArrayPut(PSDRV_PDEVICE *physDev, CHAR *pszArrayName, INT nIndex, LONG lCoord); extern BOOL PSDRV_WriteArrayDef(PSDRV_PDEVICE *physDev, CHAR *pszArrayName, INT nSize); @@ -453,6 +498,31 @@ BOOL PSDRV_GetType1Metrics(void); const AFMMETRICS *PSDRV_UVMetrics(LONG UV, const AFM *afm); SHORT PSDRV_CalcAvgCharWidth(const AFM *afm); +extern BOOL PSDRV_SelectBuiltinFont(PSDRV_PDEVICE *physDev, HFONT hfont, + LOGFONTW *plf, LPSTR FaceName); +extern BOOL PSDRV_WriteSetBuiltinFont(PSDRV_PDEVICE *physDev); +extern BOOL PSDRV_WriteBuiltinGlyphShow(PSDRV_PDEVICE *physDev, LPCWSTR str, INT count); + +extern BOOL PSDRV_SelectDownloadFont(PSDRV_PDEVICE *physDev); +extern BOOL PSDRV_WriteSetDownloadFont(PSDRV_PDEVICE *physDev); +extern BOOL PSDRV_WriteDownloadGlyphShow(PSDRV_PDEVICE *physDev, WORD *glpyhs, + UINT count); +extern BOOL PSDRV_EmptyDownloadList(PSDRV_PDEVICE *physDev); + +#define MAX_G_NAME 31 /* max length of PS glyph name */ +extern void get_glyph_name(HDC hdc, WORD index, char *name); + +extern TYPE1 *T1_download_header(PSDRV_PDEVICE *physDev, + LPOUTLINETEXTMETRICA potm, + char *ps_name); +extern BOOL T1_download_glyph(PSDRV_PDEVICE *physDev, DOWNLOAD *pdl, + DWORD index, char *glyph_name); +extern void T1_free(TYPE1 *t1); + +extern TYPE42 *T42_download_header(PSDRV_PDEVICE *physDev, + LPOUTLINETEXTMETRICA ptom, + char *ps_name); +extern BOOL T42_download_glyph(PSDRV_PDEVICE *physDev, DOWNLOAD *pdl, + DWORD index, char *glyph_name); +extern void T42_free(TYPE42 *t42); #endif - - diff --git a/dlls/wineps/text.c b/dlls/wineps/text.c index 2af7e6884d3..f459c713062 100644 --- a/dlls/wineps/text.c +++ b/dlls/wineps/text.c @@ -25,7 +25,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(psdrv); -static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, LPCWSTR str, UINT count, +static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags, + LPCWSTR str, UINT count, BOOL bDrawBackground, const INT *lpDx); /*********************************************************************** @@ -70,12 +71,12 @@ BOOL PSDRV_ExtTextOut( PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags, PSDRV_WriteClip(physDev); } - bResult = PSDRV_Text(physDev, x, y, str, count, !(bClipped && bOpaque), lpDx); + bResult = PSDRV_Text(physDev, x, y, flags, str, count, !(bClipped && bOpaque), lpDx); PSDRV_WriteGRestore(physDev); } else { - bResult = PSDRV_Text(physDev, x, y, str, count, TRUE, lpDx); + bResult = PSDRV_Text(physDev, x, y, flags, str, count, TRUE, lpDx); } return bResult; @@ -84,21 +85,28 @@ BOOL PSDRV_ExtTextOut( PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags, /*********************************************************************** * PSDRV_Text */ -static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, LPCWSTR str, UINT count, - BOOL bDrawBackground, const INT *lpDx) +static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, UINT flags, LPCWSTR str, + UINT count, BOOL bDrawBackground, const INT *lpDx) { - LPWSTR strbuf; SIZE sz; + TEXTMETRICW tm; + POINT pt; + INT ascent, descent; + WORD *glyphs = NULL; DC *dc = physDev->dc; UINT align = GetTextAlign( physDev->hdc ); if (!count) return TRUE; - strbuf = HeapAlloc( PSDRV_Heap, 0, (count + 1) * sizeof(WCHAR)); - if(!strbuf) { - WARN("HeapAlloc failed\n"); - return FALSE; + + if(physDev->font.fontloc == Download) { + if(flags & ETO_GLYPH_INDEX) + glyphs = (LPWORD)str; + else { + glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD)); + GetGlyphIndicesW(physDev->hdc, str, count, glyphs, 0); + } } if(align & TA_UPDATECP) { @@ -106,15 +114,25 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, LPCWSTR str, UINT c y = dc->CursPosY; } - x = INTERNAL_XWPTODP(dc, x, y); - y = INTERNAL_YWPTODP(dc, x, y); + pt.x = x; + pt.y = y; + LPtoDP(physDev->hdc, &pt, 1); + x = pt.x; + y = pt.y; + + if(physDev->font.fontloc == Download) + GetTextExtentPointI(physDev->hdc, glyphs, count, &sz); + else + GetTextExtentPoint32W(physDev->hdc, str, count, &sz); - GetTextExtentPoint32W(physDev->hdc, str, count, &sz); if(lpDx) { SIZE tmpsz; INT i; /* Get the width of the last char and add on all the offsets */ - GetTextExtentPoint32W(physDev->hdc, str + count - 1, 1, &tmpsz); + if(physDev->font.fontloc == Download) + GetTextExtentPointI(physDev->hdc, glyphs + count - 1, 1, &tmpsz); + else + GetTextExtentPoint32W(physDev->hdc, str + count - 1, 1, &tmpsz); for(i = 0; i < count-1; i++) tmpsz.cx += lpDx[i]; sz.cx = tmpsz.cx; /* sz.cy remains untouched */ @@ -122,6 +140,11 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, LPCWSTR str, UINT c sz.cx = INTERNAL_XWSTODS(dc, sz.cx); sz.cy = INTERNAL_YWSTODS(dc, sz.cy); + + GetTextMetricsW(physDev->hdc, &tm); + ascent = INTERNAL_YWSTODS(dc, tm.tmAscent); + descent = INTERNAL_YWSTODS(dc, tm.tmDescent); + TRACE("textAlign = %x\n", align); switch(align & (TA_LEFT | TA_CENTER | TA_RIGHT) ) { case TA_LEFT: @@ -144,27 +167,23 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, LPCWSTR str, UINT c switch(align & (TA_TOP | TA_BASELINE | TA_BOTTOM) ) { case TA_TOP: - y += physDev->font.tm.tmAscent; + y += ascent; break; case TA_BASELINE: break; case TA_BOTTOM: - y -= physDev->font.tm.tmDescent; + y -= descent; break; } - memcpy(strbuf, str, count * sizeof(WCHAR)); - *(strbuf + count) = '\0'; - if ((GetBkMode( physDev->hdc ) != TRANSPARENT) && bDrawBackground) { PSDRV_WriteGSave(physDev); PSDRV_WriteNewPath(physDev); - PSDRV_WriteRectangle(physDev, x, y - physDev->font.tm.tmAscent, sz.cx, - physDev->font.tm.tmAscent + - physDev->font.tm.tmDescent); + PSDRV_WriteRectangle(physDev, x, y - ascent, sz.cx, + ascent + descent); PSDRV_WriteSetColor(physDev, &physDev->bkColor); PSDRV_WriteFill(physDev); PSDRV_WriteGRestore(physDev); @@ -172,8 +191,12 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, LPCWSTR str, UINT c PSDRV_WriteMoveTo(physDev, x, y); - if(!lpDx) - PSDRV_WriteGlyphShow(physDev, strbuf, lstrlenW(strbuf)); + if(!lpDx) { + if(physDev->font.fontloc == Download) + PSDRV_WriteDownloadGlyphShow(physDev, glyphs, count); + else + PSDRV_WriteBuiltinGlyphShow(physDev, str, count); + } else { INT i; float dx = 0.0, dy = 0.0; @@ -181,39 +204,34 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, LPCWSTR str, UINT c float sin_theta = sin(physDev->font.escapement * M_PI / 1800.0); for(i = 0; i < count-1; i++) { TRACE("lpDx[%d] = %d\n", i, lpDx[i]); - PSDRV_WriteGlyphShow(physDev, &strbuf[i], 1); + if(physDev->font.fontloc == Download) + PSDRV_WriteDownloadGlyphShow(physDev, glyphs + i, 1); + else + PSDRV_WriteBuiltinGlyphShow(physDev, str + i, 1); dx += lpDx[i] * cos_theta; dy -= lpDx[i] * sin_theta; PSDRV_WriteMoveTo(physDev, x + INTERNAL_XWSTODS(dc, dx), y + INTERNAL_YWSTODS(dc, dy)); } - PSDRV_WriteGlyphShow(physDev, &strbuf[i], 1); + if(physDev->font.fontloc == Download) + PSDRV_WriteDownloadGlyphShow(physDev, glyphs + i, 1); + else + PSDRV_WriteBuiltinGlyphShow(physDev, str + i, 1); } /* * Underline and strikeout attributes. */ - if ((physDev->font.tm.tmUnderlined) || (physDev->font.tm.tmStruckOut)) { + if ((tm.tmUnderlined) || (tm.tmStruckOut)) { /* Get the thickness and the position for the underline attribute */ /* We'll use the same thickness for the strikeout attribute */ - float thick = physDev->font.afm->UnderlineThickness * physDev->font.scale; - float pos = -physDev->font.afm->UnderlinePosition * physDev->font.scale; - SIZE size; INT escapement = physDev->font.escapement; - TRACE("Position = %f Thickness %f Escapement %d\n", - pos, thick, escapement); - - /* Get the width of the text */ - - PSDRV_GetTextExtentPoint(physDev, strbuf, lstrlenW(strbuf), &size); - size.cx = INTERNAL_XWSTODS(dc, size.cx); - /* Do the underline */ - if (physDev->font.tm.tmUnderlined) { + if (tm.tmUnderlined) { PSDRV_WriteNewPath(physDev); /* will be closed by WriteRectangle */ if (escapement != 0) /* rotated text */ { @@ -224,10 +242,12 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, LPCWSTR str, UINT c PSDRV_WriteRotate(physDev, -escapement/10); /* draw the underline relative to the starting point */ - PSDRV_WriteRRectangle(physDev, 0, (INT)pos, size.cx, (INT)thick); + PSDRV_WriteRRectangle(physDev, 0, -physDev->font.underlinePosition, + sz.cx, physDev->font.underlineThickness); } else - PSDRV_WriteRectangle(physDev, x, y + (INT)pos, size.cx, (INT)thick); + PSDRV_WriteRectangle(physDev, x, y - physDev->font.underlinePosition, + sz.cx, physDev->font.underlineThickness); PSDRV_WriteFill(physDev); @@ -237,8 +257,7 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, LPCWSTR str, UINT c /* Do the strikeout */ - if (physDev->font.tm.tmStruckOut) { - pos = -physDev->font.tm.tmAscent / 2; + if (tm.tmStruckOut) { PSDRV_WriteNewPath(physDev); /* will be closed by WriteRectangle */ if (escapement != 0) /* rotated text */ { @@ -248,11 +267,13 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, LPCWSTR str, UINT c /* temporarily rotate the coord system */ PSDRV_WriteRotate(physDev, -escapement/10); - /* draw the underline relative to the starting point */ - PSDRV_WriteRRectangle(physDev, 0, (INT)pos, size.cx, (INT)thick); + /* draw the line relative to the starting point */ + PSDRV_WriteRRectangle(physDev, 0, -physDev->font.strikeoutPosition, + sz.cx, physDev->font.strikeoutThickness); } else - PSDRV_WriteRectangle(physDev, x, y + (INT)pos, size.cx, (INT)thick); + PSDRV_WriteRectangle(physDev, x, y - physDev->font.strikeoutPosition, + sz.cx, physDev->font.strikeoutThickness); PSDRV_WriteFill(physDev); @@ -261,6 +282,6 @@ static BOOL PSDRV_Text(PSDRV_PDEVICE *physDev, INT x, INT y, LPCWSTR str, UINT c } } - HeapFree(PSDRV_Heap, 0, strbuf); + if(glyphs && glyphs != str) HeapFree(GetProcessHeap(), 0, glyphs); return TRUE; } diff --git a/dlls/wineps/type1.c b/dlls/wineps/type1.c new file mode 100644 index 00000000000..9e136e46276 --- /dev/null +++ b/dlls/wineps/type1.c @@ -0,0 +1,299 @@ +/* + * 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 +#include +#include +#include +#include "winspool.h" +#include "psdrv.h" +#include "wine/debug.h" +#include "winerror.h" +#include "config.h" +#include "wine/port.h" + +WINE_DEFAULT_DEBUG_CHANNEL(psdrv); + +struct tagTYPE1 { + DWORD glyph_sent_size; + BOOL *glyph_sent; + DWORD emsize; + HFONT unscaled_font; +}; + +#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, LPOUTLINETEXTMETRICA potm, + char *ps_name) +{ + char *buf; + TYPE1 *t1; + LOGFONTW lf; + + 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 = potm->otmEMSquare; + + GetObjectW(GetCurrentObject(physDev->hdc, OBJ_FONT), sizeof(lf), &lf); + lf.lfHeight = -t1->emsize; + t1->unscaled_font = CreateFontIndirectW(&lf); + 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, + potm->otmrcFontBox.left, potm->otmrcFontBox.bottom, + potm->otmrcFontBox.right, potm->otmrcFontBox.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; + GLYPHMETRICS gm; + char *glyph_buf; + POINT curpos; + TTPOLYGONHEADER *pph; + TTPOLYCURVE *ppc; + 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))); + } + + old_font = SelectObject(physDev->hdc, t1->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); + + 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); + DeleteObject(t1->unscaled_font); + HeapFree(GetProcessHeap(), 0, t1); + return; +} diff --git a/dlls/wineps/type42.c b/dlls/wineps/type42.c new file mode 100644 index 00000000000..35c384bd093 --- /dev/null +++ b/dlls/wineps/type42.c @@ -0,0 +1,320 @@ +/* + * PostScript driver Type42 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 +#include +#include +#include +#include "winspool.h" +#include "psdrv.h" +#include "wine/debug.h" +#include "winerror.h" +#include "config.h" +#include "wine/port.h" + +WINE_DEFAULT_DEBUG_CHANNEL(psdrv); + + +#define GET_BE_WORD(ptr) MAKEWORD( ((BYTE *)(ptr))[1], ((BYTE *)(ptr))[0] ) +#define GET_BE_DWORD(ptr) ((DWORD)MAKELONG( GET_BE_WORD(&((WORD *)(ptr))[1]), \ + GET_BE_WORD(&((WORD *)(ptr))[0]) )) + +#define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ + ( ( (DWORD)_x4 << 24 ) | \ + ( (DWORD)_x3 << 16 ) | \ + ( (DWORD)_x2 << 8 ) | \ + (DWORD)_x1 ) + +typedef struct { + DWORD MS_tag; + DWORD len, check; + BYTE *data; + BOOL write; +} OTTable; + +const OTTable tables_templ[] = { + { MS_MAKE_TAG('c','v','t',' '), 0, 0, NULL, TRUE }, + { MS_MAKE_TAG('f','p','g','m'), 0, 0, NULL, TRUE }, + { MS_MAKE_TAG('g','d','i','r'), 0, 0, NULL, TRUE }, + { MS_MAKE_TAG('g','l','y','f'), 0, 0, NULL, FALSE }, + { MS_MAKE_TAG('h','e','a','d'), 0, 0, NULL, TRUE }, + { MS_MAKE_TAG('h','h','e','a'), 0, 0, NULL, TRUE }, + { MS_MAKE_TAG('h','m','t','x'), 0, 0, NULL, FALSE }, + { MS_MAKE_TAG('l','o','c','a'), 0, 0, NULL, FALSE }, + { MS_MAKE_TAG('m','a','x','p'), 0, 0, NULL, TRUE }, + { MS_MAKE_TAG('p','r','e','p'), 0, 0, NULL, TRUE }, + { 0, 0, 0, NULL, 0 } +}; + +struct tagTYPE42 { + OTTable tables[sizeof(tables_templ)/sizeof(tables_templ[0])]; + int glyf_tab, loca_tab, head_tab; /* indices of glyf, loca and head tables */ + int hmtx_tab; + DWORD glyph_sent_size; + BOOL *glyph_sent; + DWORD emsize; +}; + +#define GLYPH_SENT_INC 128 + +#define FLIP_ORDER(x) \ + ( ( ((x) & 0xff) << 24) | \ + ( ((x) & 0xff00) << 8) | \ + ( ((x) & 0xff0000) >> 8) | \ + ( ((x) & 0xff000000) >> 24) ) + + +/* Some flags for composite glyphs. See glyf table in OT spec */ +#define ARG_1_AND_2_ARE_WORDS (1L << 0) +#define WE_HAVE_A_SCALE (1L << 3) +#define MORE_COMPONENTS (1L << 5) +#define WE_HAVE_AN_X_AND_Y_SCALE (1L << 6) +#define WE_HAVE_A_TWO_BY_TWO (1L << 7) + +static BOOL LoadTable(HDC hdc, OTTable *table) +{ + int i; + + if(table->MS_tag == MS_MAKE_TAG('g','d','i','r')) return TRUE; + table->len = GetFontData(hdc, table->MS_tag, 0, NULL, 0); + table->data = HeapAlloc(GetProcessHeap(), 0, (table->len + 3) & ~3 ); + memset(table->data + ((table->len - 1) & ~3), 0, sizeof(DWORD)); + GetFontData(hdc, table->MS_tag, 0, table->data, table->len); + table->check = 0; + for(i = 0; i < (table->len + 3) / 4; i++) + table->check += FLIP_ORDER(*((DWORD*)(table->data) + i)); + return TRUE; +} + + +TYPE42 *T42_download_header(PSDRV_PDEVICE *physDev, LPOUTLINETEXTMETRICA potm, + char *ps_name) +{ + DWORD i, j, tablepos; + WORD num_of_tables = sizeof(tables_templ) / sizeof(tables_templ[0]) - 1; + WORD num_of_write_tables = 0; + char *buf; + TYPE42 *t42; + char start[] = /* name, fontbbox */ + "25 dict begin\n" + " /FontName /%s def\n" + " /Encoding 256 array 0 1 255{1 index exch /.notdef put} for\n" + " def\n" + " /PaintType 0 def\n" + " /FontMatrix [1 0 0 1 0 0] def\n" + " /FontBBox [%f %f %f %f] def\n" + " /FontType 42 def\n" + " /CharStrings 256 dict begin\n" + " /.notdef 0 def\n" + " currentdict end def\n" + " /GlyphDirectory 256 dict def\n" + " /Metrics 256 dict def\n" + " /sfnts [\n"; + char TT_offset_table[] = "<00010000%04x%04x%04x%04x\n"; + char TT_table_dir_entry[] = "%08lx%08lx%08lx%08lx\n"; + char end[] = "] def\n" + "currentdict end dup /FontName get exch definefont pop\n"; + + + t42 = HeapAlloc(GetProcessHeap(), 0, sizeof(*t42)); + memcpy(t42->tables, tables_templ, sizeof(tables_templ)); + t42->loca_tab = t42->glyf_tab = t42->head_tab = t42->hmtx_tab = -1; + t42->glyph_sent_size = GLYPH_SENT_INC; + t42->glyph_sent = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + t42->glyph_sent_size * + sizeof(*(t42->glyph_sent))); + t42->emsize = potm->otmEMSquare; + + for(i = 0; i < num_of_tables; i++) { + LoadTable(physDev->hdc, t42->tables + i); + if(t42->tables[i].write) num_of_write_tables++; + if(t42->tables[i].MS_tag == MS_MAKE_TAG('l','o','c','a')) + t42->loca_tab = i; + else if(t42->tables[i].MS_tag == MS_MAKE_TAG('g','l','y','f')) + t42->glyf_tab = i; + else if(t42->tables[i].MS_tag == MS_MAKE_TAG('h','e','a','d')) + t42->head_tab = i; + else if(t42->tables[i].MS_tag == MS_MAKE_TAG('h','m','t','x')) + t42->hmtx_tab = i; + } + + buf = HeapAlloc(GetProcessHeap(), 0, sizeof(start) + strlen(ps_name) + + 100); + + sprintf(buf, start, ps_name, + (float)potm->otmrcFontBox.left / potm->otmEMSquare, + (float)potm->otmrcFontBox.bottom / potm->otmEMSquare, + (float)potm->otmrcFontBox.right / potm->otmEMSquare, + (float)potm->otmrcFontBox.top / potm->otmEMSquare); + + PSDRV_WriteSpool(physDev, buf, strlen(buf)); + + sprintf(buf, TT_offset_table, num_of_write_tables, + num_of_write_tables, num_of_write_tables, num_of_write_tables); + + PSDRV_WriteSpool(physDev, buf, strlen(buf)); + + tablepos = 12 + num_of_write_tables * 16; + for(i = 0; i < num_of_tables; i++) { + if(!t42->tables[i].write) continue; + sprintf(buf, TT_table_dir_entry, FLIP_ORDER(t42->tables[i].MS_tag), + t42->tables[i].check, t42->tables[i].len ? tablepos : 0, + t42->tables[i].len); + PSDRV_WriteSpool(physDev, buf, strlen(buf)); + tablepos += ((t42->tables[i].len + 3) & ~3); + } + PSDRV_WriteSpool(physDev, ">\n", 2); + + for(i = 0; i < num_of_tables; i++) { + if(t42->tables[i].len == 0 || !t42->tables[i].write) continue; + PSDRV_WriteSpool(physDev, "<", 1); + for(j = 0; j < ((t42->tables[i].len + 3) & ~3); j++) { + sprintf(buf, "%02x", t42->tables[i].data[j]); + PSDRV_WriteSpool(physDev, buf, strlen(buf)); + if(j % 16 == 15) PSDRV_WriteSpool(physDev, "\n", 1); + } + PSDRV_WriteSpool(physDev, ">\n", 2); + } + + PSDRV_WriteSpool(physDev, end, sizeof(end) - 1); + HeapFree(GetProcessHeap(), 0, buf); + return t42; +} + + + + +BOOL T42_download_glyph(PSDRV_PDEVICE *physDev, DOWNLOAD *pdl, DWORD index, + char *glyph_name) +{ + DWORD start, end, i; + char *buf; + TYPE42 *t42; + WORD loca_format; + WORD awidth; + short lsb; + char glyph_def[] = + "/%s findfont exch 1 index /GlyphDirectory get\n" + "begin\n" + " %d exch def\n" + "end\n" + "dup /CharStrings get\n" + "begin\n" + " /%s %d def\n" + "end\n" + "/Metrics get\n" + "begin\n" + " /%s [%f %f] def\n" + "end\n"; + + + TRACE("%ld %s\n", index, glyph_name); + assert(pdl->type == Type42); + t42 = pdl->typeinfo.Type42; + + if(index < t42->glyph_sent_size) { + if(t42->glyph_sent[index]) + return TRUE; + } else { + t42->glyph_sent_size = (index / GLYPH_SENT_INC + 1) * GLYPH_SENT_INC; + t42->glyph_sent = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, + t42->glyph_sent, + t42->glyph_sent_size * sizeof(*(t42->glyph_sent))); + } + + buf = HeapAlloc(GetProcessHeap(), 0, sizeof(glyph_def) + + strlen(pdl->ps_name) + 100); + + loca_format = GET_BE_WORD(t42->tables[t42->head_tab].data + 50); + TRACE("loca_format = %d\n", loca_format); + switch(loca_format) { + case 0: + start = GET_BE_WORD(((WORD*)t42->tables[t42->loca_tab].data) + index); + start <<= 1; + end = GET_BE_WORD(((WORD*)t42->tables[t42->loca_tab].data) + index + 1); + end <<= 1; + break; + case 1: + start = GET_BE_DWORD(((DWORD*)t42->tables[t42->loca_tab].data) + index); + end = GET_BE_DWORD(((DWORD*)t42->tables[t42->loca_tab].data) + index + 1); + break; + default: + ERR("Unknown loca_format %d\n", loca_format); + return FALSE; + } + TRACE("start = %lx end = %lx\n", start, end); + + awidth = GET_BE_WORD(t42->tables[t42->hmtx_tab].data + index * 4); + lsb = GET_BE_WORD(t42->tables[t42->hmtx_tab].data + index * 4 + 2); + + if(GET_BE_WORD(t42->tables[t42->glyf_tab].data + start) == 0xffff) { + /* Composite glyph */ + char *sg_start = t42->tables[t42->glyf_tab].data + start + 10; + DWORD sg_flags, sg_index; + char sg_name[MAX_G_NAME + 1]; + + do { + sg_flags = GET_BE_WORD(sg_start); + sg_index = GET_BE_WORD(sg_start + 2); + + TRACE("Sending subglyph %04lx for glyph %04lx\n", sg_index, index); + get_glyph_name(physDev->hdc, sg_index, sg_name); + T42_download_glyph(physDev, pdl, sg_index, sg_name); + sg_start += 4; + if(sg_flags & ARG_1_AND_2_ARE_WORDS) + sg_start += 4; + else + sg_start += 2; + if(sg_flags & WE_HAVE_A_SCALE) + sg_start += 2; + else if(sg_flags & WE_HAVE_AN_X_AND_Y_SCALE) + sg_start += 4; + else if(sg_flags & WE_HAVE_A_TWO_BY_TWO) + sg_start += 8; + } while(sg_flags & MORE_COMPONENTS); + } + + sprintf(buf, "%%%%glyph %04lx\n", index); + PSDRV_WriteSpool(physDev, buf, strlen(buf)); + PSDRV_WriteSpool(physDev, "<", 1); + for(i = start; i < end; i++) { + sprintf(buf, "%02x", *(t42->tables[t42->glyf_tab].data + i)); + PSDRV_WriteSpool(physDev, buf, strlen(buf)); + if((i - start) % 16 == 15) + PSDRV_WriteSpool(physDev, "\n", 1); + } + PSDRV_WriteSpool(physDev, ">\n", 2); + sprintf(buf, glyph_def, pdl->ps_name, index, glyph_name, index, + glyph_name, (float)lsb / t42->emsize, (float)awidth / t42->emsize); + PSDRV_WriteSpool(physDev, buf, strlen(buf)); + + t42->glyph_sent[index] = TRUE; + HeapFree(GetProcessHeap(), 0, buf); + return TRUE; +} + +void T42_free(TYPE42 *t42) +{ + OTTable *table; + for(table = t42->tables; table->MS_tag; table++) + HeapFree(GetProcessHeap(), 0, table->data); + HeapFree(GetProcessHeap(), 0, t42->glyph_sent); + HeapFree(GetProcessHeap(), 0, t42); + return; +}