Commit ae4278ee authored by Huw D M Davies's avatar Huw D M Davies Committed by Alexandre Julliard

Added Type 1 and Type 42 font downloading.

Misc bug fixes.
parent 7a6ea919
......@@ -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
......
......@@ -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;
}
/*
* 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 <string.h>
#include <stdlib.h>
#include <assert.h>
#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;
}
/*
* 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 <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#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;
}
......@@ -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;
}
......
......@@ -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;
}
......
......@@ -18,135 +18,22 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <string.h>
#include <stdlib.h> /* for bsearch() */
#include <assert.h>
#include <stdlib.h>
#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;
}
......@@ -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);
......
......@@ -21,6 +21,7 @@
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#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;
for (i = 0; i < count; ++i)
{
LPCSTR name;
int l;
int l;
name = PSDRV_UVMetrics(str[i], physDev->font.afm)->N->sz;
l = snprintf(buf, sizeof(buf), psglyphshow, name);
l = snprintf(buf, sizeof(buf), psglyphshow, g_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;
}
......@@ -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
......@@ -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;
}
/*
* 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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#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;
}
/*
* 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 <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#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;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment