|
|
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
text.cpp
Abstract:
font/text output handling functions implementation
Environment:
Windows Whistler
Revision History:
04/6/99 Created initial framework.
--*/
#include "lib.h"
#include "gpd.h"
#include "winres.h"
#include "pdev.h"
#include "common.h"
#include "..\..\font\font.h"
#include "xlpdev.h"
#include "xldebug.h"
#include <assert.h>
#include "pclxlcmd.h"
#include "pclxle.h"
#include "xlgstate.h"
#include "xloutput.h"
#include "xltext.h"
#include "xlbmpcvt.h"
#include "pclxlcmn.h"
#include "xltt.h"
#include "math.h"
//
// TrueType outline format switch
//
#define CLASS12 1
#define COMPGLYF 1
//
// Local functions prototypes
//
DWORD DwDownloadCompositeGlyph( PDEVOBJ pdevobj, ULONG ulFontID, PGLYF pGlyph);
BOOL BDownloadGlyphData( PDEVOBJ pdevobj, ULONG ulFontID, DWORD dwGlyphID, HGLYPH hGlyph, PBYTE pubGlyphData, DWORD dwGlyphDataSize, BOOL bSpace);
extern "C" HRESULT APIENTRY PCLXLDownloadCharGlyph( PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, HGLYPH hGlyph, PDWORD pdwWidth, OUT DWORD *pdwResult);
//
// XL Text entry point
//
extern "C" BOOL APIENTRY PCLXLTextOutAsBitmap( SURFOBJ *pso, STROBJ *pstro, FONTOBJ *pfo, CLIPOBJ *pco, RECTL *prclExtra, RECTL *prclOpaque, BRUSHOBJ *pboFore, BRUSHOBJ *pboOpaque, POINTL *pptlOrg, MIX mix) /*++
Routine Description:
IPrintOemUni TextOutAsBitmap interface
Arguments:
Return Value:
Note:
--*/ { VERBOSE(("PCLXLTextOutAsBitmap() entry.\r\n"));
PDEVOBJ pdevobj = (PDEVOBJ)pso->dhpdev; PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM; GLYPHPOS *pGlyphPos; PATHOBJ *pPathObj; GLYPHBITS *pGlyphBits; GLYPHDATA *pGlyphData;
HRESULT hResult; ULONG ulJ, ulGlyphs, ulCount, ulcbBmpSize, ulcbLineAlign, ulcbLineSize; LONG lI; BOOL bMore; PBYTE pubBitmap; BYTE aubDataHdr[8]; BYTE aubZero[8] = {0, 0, 0, 0, 0, 0, 0, 0}; DWORD adwColorTable[2]; DWORD dwDataHdrSize;
if (pstro->cGlyphs == 0) { VERBOSE(("PCLXLTextOutAsBitmap: cGlyphs = 0\n")); return TRUE; }
XLOutput *pOutput = pxlpdev->pOutput;
//
// UNIDRV switchs the format of font in the middle of downloading
// character glyphs. We need to end the BeginChar sequence.
//
if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Send_cmd(eEndChar); }
ROP4 rop = UlVectMixToRop4(mix);
if ( S_OK != pOutput->SetClip(pco) || S_OK != pOutput->SetPenColor(NULL, NULL) || S_OK != pOutput->Flush(pdevobj)) return FALSE;
STROBJ_vEnumStart(pstro);
do { bMore = STROBJ_bEnum (pstro, &ulGlyphs, &pGlyphPos);
if (bMore == DDI_ERROR) { return FALSE; }
for (ulCount = 0; ulCount < ulGlyphs; ulCount++, pGlyphPos++) { //
// get the path of the glyph from the FONTOBJ
//
if (!FONTOBJ_cGetGlyphs (pfo, FO_PATHOBJ, 1, &pGlyphPos->hg, (PVOID *)&pPathObj)) { ERR(("PCLXLTextOutAsBitmap: cGetGlyphs failed\n")); hResult = S_FALSE; } else { if (S_OK == pOutput->Send_cmd(ePushGS) && S_OK == pOutput->SetBrush(pboFore, pptlOrg) && S_OK == pOutput->SetPageOrigin((uint16)pGlyphPos->ptl.x, (uint16)pGlyphPos->ptl.x) && S_OK == pOutput->Path(pPathObj) && S_OK == pOutput->Paint() && S_OK == pOutput->Send_cmd(ePopGS)) hResult = S_OK; else hResult = S_FALSE; }
if (hResult == S_FALSE) { pOutput->Delete();
adwColorTable[1] = 0x00FFFFFF;
if (pboFore) { if (pboFore->iSolidColor == NOT_SOLID_COLOR) { adwColorTable[0] = BRUSHOBJ_ulGetBrushColor(pboFore); } else { adwColorTable[0] = pboFore->iSolidColor; } } else adwColorTable[0] = 0x00000000;
//
// get the path of the glyph from the FONTOBJ
//
if (!FONTOBJ_cGetGlyphs (pfo, FO_GLYPHBITS, 1, &pGlyphPos->hg, (PVOID *)&pGlyphData)) { ERR(("PCLXLTextOutAsBitmap: cGetGlyphs failed\n")); return FALSE; }
pGlyphBits = pGlyphData->gdf.pgb; ulcbLineSize = (pGlyphBits->sizlBitmap.cx + 7) >> 3; ulcbLineAlign = (sizeof(DWORD) - ulcbLineSize % sizeof(DWORD)) % sizeof(DWORD); ulcbBmpSize = (ulcbLineSize + ulcbLineAlign) * pGlyphBits->sizlBitmap.cy; if (ulcbBmpSize <= 0xff) { aubDataHdr[0] = PCLXL_dataLengthByte; aubDataHdr[1] = (BYTE)(ulcbBmpSize & 0xff); dwDataHdrSize = 2; } else { aubDataHdr[0] = PCLXL_dataLength; aubDataHdr[1] = (BYTE)(ulcbBmpSize & 0xff); aubDataHdr[2] = (BYTE)((ulcbBmpSize >> 8) & 0xff); aubDataHdr[3] = (BYTE)((ulcbBmpSize >> 16) & 0xff); aubDataHdr[4] = (BYTE)((ulcbBmpSize >> 24) & 0xff); dwDataHdrSize = 5; }
//
// Hack ROP for Print As Graphics
//
rop = 0xFC;
if (S_OK == pOutput->SetCursor(pGlyphPos->ptl.x + pGlyphBits->ptlOrigin.x, pGlyphPos->ptl.y + pGlyphBits->ptlOrigin.y) && S_OK == pOutput->SetROP3(GET_FOREGROUND_ROP3(rop)) && S_OK == pOutput->SetPaintTxMode(eOpaque) && S_OK == pOutput->SetSourceTxMode(eTransparent)) { hResult = S_OK; } else { hResult = S_FALSE; }
if (pOutput->GetDeviceColorDepth() != e24Bit) { if (S_OK == hResult && S_OK == pOutput->SetColorSpace(eGray) && S_OK == pOutput->Send_cmd(eSetColorSpace) && S_OK == pOutput->SetBrush(pboFore, pptlOrg) && S_OK == pOutput->SetOutputBPP(eDirectPixel, 1)) { hResult = S_OK; } else { hResult = S_FALSE; } } else { if (S_OK == hResult && S_OK == pOutput->SetColorSpace(eRGB) && S_OK == pOutput->SetPaletteDepth(e8Bit) && S_OK == pOutput->SetPaletteData(pOutput->GetDeviceColorDepth(), 2, adwColorTable) && S_OK == pOutput->Send_cmd(eSetColorSpace) && S_OK == pOutput->SetOutputBPP(eIndexedPixel, 1)) { hResult = S_OK; } else { hResult = S_FALSE; } }
if (S_OK == hResult && S_OK == pOutput->SetSourceWidth((uint16)pGlyphBits->sizlBitmap.cx) && S_OK == pOutput->SetSourceHeight((uint16)pGlyphBits->sizlBitmap.cy) && S_OK == pOutput->SetDestinationSize((uint16)pGlyphBits->sizlBitmap.cx, (uint16)pGlyphBits->sizlBitmap.cy) && S_OK == pOutput->Send_cmd(eBeginImage) && S_OK == pOutput->ReadImage(pGlyphBits->sizlBitmap.cy, eNoCompression) && S_OK == pOutput->Flush(pdevobj)) hResult = S_OK; else hResult = S_FALSE;
WriteSpoolBuf((PPDEV)pdevobj, aubDataHdr, dwDataHdrSize);
pubBitmap = pGlyphBits->aj;
//
// Bitmap data has to be DWORD-align.
//
// Invert bitmap
//
for (lI = 0; lI < pGlyphBits->sizlBitmap.cy; lI ++) { for (ulJ = 0; ulJ < ulcbLineSize; ulJ++) { *(pubBitmap+ulJ) = ~*(pubBitmap+ulJ); } WriteSpoolBuf((PPDEV)pdevobj, pubBitmap, ulcbLineSize); pubBitmap += ulcbLineSize; WriteSpoolBuf((PPDEV)pdevobj, aubZero, ulcbLineAlign); }
if (S_OK == hResult && S_OK == pOutput->Send_cmd(eEndImage) && S_OK == pOutput->Flush(pdevobj)) hResult = S_OK; else hResult = S_FALSE; } else hResult = pOutput->Flush(pdevobj);
} } while (bMore && hResult == S_OK);
if (S_OK == hResult) return TRUE; else return FALSE; }
extern "C" HRESULT APIENTRY PCLXLDownloadFontHeader( PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, OUT DWORD *pdwResult) /*++
Routine Description:
IPrintOemUni DownloadFontHeader interface
Arguments:
Return Value:
Note:
--*/ { VERBOSE(("PCLXLDownloadFontHeader() entry.\r\n"));
PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM;
HRESULT hResult;
if (NULL == pxlpdev) { ERR(("PCLXL:DownloadFontHeader Invalid pdevOEM.\r\n")); return S_FALSE; }
//
// UNIDRV switchs the format of font in the middle of downloading
// character glyphs. We need to end the BeginChar sequence.
//
if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { XLOutput *pOutput = pxlpdev->pOutput; pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Send_cmd(eEndChar); }
if (pUFObj->dwFlags & UFOFLAG_TTDOWNLOAD_BITMAP) { VERBOSE(("PCLXLDownloadFontHeader() BITMAP.\n"));
//
// Get current text resolution
//
if (pxlpdev->dwTextRes == 0) { GETINFO_STDVAR StdVar; DWORD dwSizeNeeded;
StdVar.dwSize = sizeof(GETINFO_STDVAR); StdVar.dwNumOfVariable = 1; StdVar.StdVar[0].dwStdVarID = FNT_INFO_TEXTYRES; StdVar.StdVar[0].lStdVariable = 0; pUFObj->pfnGetInfo(pUFObj, UFO_GETINFO_STDVARIABLE, &StdVar, StdVar.dwSize, &dwSizeNeeded);
pxlpdev->dwTextRes = StdVar.StdVar[0].lStdVariable; }
//
// PCL XL FontHeader initialization
// Get the max character number from GPD file.
//
PCLXL_FONTHEADER PCLXLFontHeader; PCLXLFontHeader.ubFormat = 0; PCLXLFontHeader.ubOrientation = ePortraitOrientation; PCLXLFontHeader.wMapping = 0x0200; PCLXLFontHeader.ubFontScallingTech = eBitmap; PCLXLFontHeader.ubVariety = 0; PCLXLFontHeader.wNumOfChars = SWAPW(1+((PPDEV)pdevobj)->pGlobals->dwMaxGlyphID - ((PPDEV)pdevobj)->pGlobals->dwMinGlyphID);
//
// BR Segment initialization
//
PCLXL_BR_SEGMENT PCLXLBRSegment; PCLXLBRSegment.wSignature = PCLXL_BR_SIGNATURE; PCLXLBRSegment.wSegmentSize = 0; PCLXLBRSegment.wSegmentSizeAlign = SWAPW(PCLXL_BR_SEGMENT_SIZE); PCLXLBRSegment.wXResolution = SWAPW(pxlpdev->dwTextRes); PCLXLBRSegment.wYResolution = SWAPW(pxlpdev->dwTextRes);
//
// NULL Segment initialization
//
PCLXL_NULL_SEGMENT PCLXLNULLSegment; PCLXLNULLSegment.wSignature = PCLXL_NULL_SIGNATURE; PCLXLNULLSegment.wSegmentSize = 0; PCLXLNULLSegment.wSegmentSizeAlign = 0;
{ //
// Output
//
XLOutput *pOutput = pxlpdev->pOutput;
//
// BeginFontHeader
//
pOutput->Send_ubyte(0); pOutput->Send_attr_ubyte(eFontFormat); pOutput->Send_ubyte_array_header(16); pOutput->Write(PubGetFontName(pdevobj, pUFObj->ulFontID), PCLXL_FONTNAME_SIZE); pOutput->Send_attr_ubyte(eFontName); pOutput->Send_cmd(eBeginFontHeader);
//
// ReadFontHeader
//
uint32 uint32_FontHeaderSize; uint32_FontHeaderSize = sizeof(PCLXLFontHeader);
pOutput->Send_uint16((uint16)uint32_FontHeaderSize); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader); pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)uint32_FontHeaderSize); pOutput->Write((PBYTE)&PCLXLFontHeader, uint32_FontHeaderSize);
uint32_FontHeaderSize = sizeof(PCLXLBRSegment); pOutput->Send_uint16((uint16)uint32_FontHeaderSize); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader); pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)uint32_FontHeaderSize); pOutput->Write((PBYTE)&PCLXLBRSegment, uint32_FontHeaderSize);
uint32_FontHeaderSize = sizeof(PCLXLNULLSegment); pOutput->Send_uint16((uint16)uint32_FontHeaderSize); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader); pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)uint32_FontHeaderSize); pOutput->Write((PBYTE)&PCLXLNULLSegment, uint32_FontHeaderSize);
//
// EndFontHeader
//
pOutput->Send_cmd(eEndFontHeader);
pOutput->Flush(pdevobj); }
*pdwResult = sizeof(PCLXL_FONTHEADER) + sizeof(PCLXL_BR_SEGMENT) + sizeof(PCLXL_NULL_SEGMENT); hResult = S_OK; } else if (pUFObj->dwFlags & UFOFLAG_TTDOWNLOAD_TTOUTLINE) { VERBOSE(("PCLXLDownloadFontHeader() OUTLINE.\n"));
//
// Get FONTOBJ
//
FONTOBJ *pFontObj; if (S_OK != GetFONTOBJ(pdevobj, pUFObj, &pFontObj)) { ERR(("PCLXL:DownloadFontHeader UFO_GETINFO_FONTOBJ failed.\r\n")); return E_UNEXPECTED; }
//
// ASSUMPTION: pxlpdev->pTTFile is initialized in EnablePDEV.
// The pointer is always available.
//
XLTrueType *pTTFile = pxlpdev->pTTFile; if (S_OK != pTTFile->SameFont(pFontObj)) { if (S_OK != pTTFile->OpenTTFile(pFontObj)) { ERR(("PCLXL:DownloadFontHeader XLTrueType>OpenTTFile failed.\r\n")); return E_UNEXPECTED; } } else pTTFile = pxlpdev->pTTFile;
//
// PCL XL FontHeader initialization
// Get the max character number from GPD file.
//
PCLXL_FONTHEADER PCLXLFontHeader; PCLXLFontHeader.ubFormat = 0; PCLXLFontHeader.ubOrientation = ePortraitOrientation; PCLXLFontHeader.wMapping = 0x0200; PCLXLFontHeader.ubFontScallingTech = eTrueType; PCLXLFontHeader.ubVariety = 0; PCLXLFontHeader.wNumOfChars = SWAPW(1+((PPDEV)pdevobj)->pGlobals->dwMaxGlyphID - ((PPDEV)pdevobj)->pGlobals->dwMinGlyphID);
//
// PCL XL GT Table Directory
//
PTTDIR pTableDir; TTTag tag; DWORD dwI, dwTableOffset, dwNumTag, dwGTSegSize, dwDWAlign, dwTableSize;
//
// GetNumOfTag returns 11 tags including loca table.
// Header requires
// head
// maxp
// gdir
// hhea (only for class 0)
// hmtx (only for class 0)
// vhea (only for vertical font and class 0)
// vmtx (only for vertical font and class 0)
//
// Optional
// cvt
// fpgm
// perp
//
// We need to get the number of Tag to download.
// XLTrueType object caches available table directories includeing loca
// table. Here we go through the cached table to see if which one of
// above table is available.
//
// See truetype.h
// TagID_first = 0. TagID_First is the number of tags which are used for
// font header.
//
dwNumTag = 0; dwGTSegSize = 0;
PCLXL_GT_TABLE_DIR PCLXLGTTblDir[TagID_Header]; for (dwI = (USHORT)TagID_First; dwI < (USHORT)TagID_Header; dwI ++) { //
// Check a table for the tag is available in the TrueType font.
//
tag = TTTag_INVALID; pTableDir = NULL;
#if CLASS12
//
// Support only Class 1 and Class 2
//
if (dwI == TagID_hhea || dwI == TagID_hmtx || dwI == TagID_vhea || dwI == TagID_vmtx ) { continue; } #else
//
// Support Class 1 and Class 2 for horizontal font.
// Class 0 for vertical font. PCL XL interpreter doesn't work fine.
//
if (S_OK != pTTFile->IsVertical()) { if (dwI == TagID_hhea || dwI == TagID_hmtx || dwI == TagID_vhea || dwI == TagID_vmtx ) { continue; } } #endif
if (S_OK == pTTFile->TagAndID(&dwI, &tag) && S_OK == pTTFile->GetTableDir(tag, (PVOID*)&pTableDir)) { //
// dwTableOffset is an offset from the top of the TrueType
// Soft Font Directory Header to the start of the table data in
// the PCL XL embedded data stream.
//
if (pTableDir) { PCLXLGTTblDir[dwNumTag].dwTableTag = pTableDir->ulTag; //PCLXLGTTblDir[dwNumTag].dwTableCheckSum = pTableDir->ulCheckSum;
PCLXLGTTblDir[dwNumTag].dwTableCheckSum = 0; PCLXLGTTblDir[dwNumTag].dwTableOffset = 0;
//
// DWORD alignment
//
dwTableSize = SWAPDW(pTableDir->ulLength); dwTableSize = ((dwTableSize + 3) >> 2) << 2;
PCLXLGTTblDir[dwNumTag].dwTableSize = SWAPDW(dwTableSize); }
dwNumTag ++; } else if (tag == TTTag_gdir) { //
// 'gdir' special case.
//
PCLXLGTTblDir[dwNumTag].dwTableTag = TTTag_gdir; PCLXLGTTblDir[dwNumTag].dwTableCheckSum = 0; PCLXLGTTblDir[dwNumTag].dwTableOffset = 0; PCLXLGTTblDir[dwNumTag].dwTableSize = 0; dwNumTag ++; } }
dwGTSegSize = sizeof(PCLXL_GT_TABLE_DIR_HEADER) + sizeof(TTDIR) * dwNumTag; dwTableOffset = sizeof(PCLXL_GT_TABLE_DIR_HEADER) + dwNumTag * sizeof(TTDIR);
//
// Set dwTableOffset in PCLXLGTTblDir
//
for (dwI = 0; dwI < dwNumTag; dwI ++) { //
// Skip virtual glyph data table (gdir)
//
if (PCLXLGTTblDir[dwI].dwTableTag != TTTag_gdir) { PCLXLGTTblDir[dwI].dwTableOffset = SWAPDW(dwTableOffset);
dwTableSize = SWAPDW(PCLXLGTTblDir[dwI].dwTableSize); dwTableOffset += dwTableSize; dwGTSegSize += dwTableSize; } else { //
// Fill gdir table dir offset
//
PCLXLGTTblDir[dwNumTag - 1].dwTableOffset = 0; }
VERBOSE(("PCLXLDownloadFontHeader:Tag[%d]=%c%c%c%c, Size=0x%0x, Offset=0x%0x\n", dwI, 0xff & PCLXLGTTblDir[dwI].dwTableTag, 0xff & (PCLXLGTTblDir[dwI].dwTableTag >> 8), 0xff & (PCLXLGTTblDir[dwI].dwTableTag >> 16), 0xff & (PCLXLGTTblDir[dwI].dwTableTag >> 24), PCLXLGTTblDir[dwI].dwTableSize, PCLXLGTTblDir[dwI].dwTableOffset)); }
//
// PCL XL GT Segment initialization
//
PTTHEADER pTTHeader; if (S_OK != pTTFile->GetHeader(&pTTHeader)) { ERR(("PCLXL:DownloadFontHeader XLTTFile::GetHeader failed.\r\n")); return S_FALSE; }
PCLXL_GT_SEGMENT PCLXLGTSegment; PCLXLGTSegment.wSignature = PCLXL_GT_SIGNATURE; PCLXLGTSegment.wSegmentSize1 = HIWORD(dwGTSegSize); PCLXLGTSegment.wSegmentSize1 = SWAPW(PCLXLGTSegment.wSegmentSize1); PCLXLGTSegment.wSegmentSize2 = LOWORD(dwGTSegSize); PCLXLGTSegment.wSegmentSize2 = SWAPW(PCLXLGTSegment.wSegmentSize2);
PCLXL_GT_TABLE_DIR_HEADER PCLXLDirHeader;
//
// N = Number of Tables
// Search Range = (maximum power of 2 <= N) * 16
// Entry Selector = Log2(maximum power of 2 <= N)
// Range Shift = (N * 16) - Search Range
//
WORD wSearchRange, wEntrySelector, wTemp; wSearchRange = 2; for (wSearchRange = 2; wSearchRange <= dwNumTag; wSearchRange <<= 1); wSearchRange >>= 1;
wTemp = wSearchRange; wSearchRange <<= 4;
for (wEntrySelector = 0; wTemp > 1; wTemp >>= 1, wEntrySelector++);
//
// HP Monolithic driver set 'ttcf' in the SFNTVersion.
//
{ HRESULT hRet; if (S_OK == (hRet = pTTFile->IsTTC())) { PCLXLDirHeader.dwSFNTVersion = TTTag_ttcf; } else if (S_FALSE == hRet) { PCLXLDirHeader.dwSFNTVersion = pTTHeader->dwSfntVersion; } else { ERR(("PCLXL:DownloadFontHeader XLTrueType.IsTTC failed.\r\n")); return E_UNEXPECTED; } } PCLXLDirHeader.wNumOfTables = SWAPW((WORD)dwNumTag); PCLXLDirHeader.wSearchRange = SWAPW(wSearchRange); PCLXLDirHeader.wEntrySelector= SWAPW(wEntrySelector); PCLXLDirHeader.wRangeShift = SWAPW((dwNumTag << 4) - wSearchRange);
//
// GC Segment initialization
//
PCLXL_GC_SEGMENT PCLXLGCSegment; PCLXLGCSegment.wSignature = PCLXL_GC_SIGNATURE; PCLXLGCSegment.wSegmentSize = 0; PCLXLGCSegment.wSegmentSizeAlign = SWAPW(PCLXL_GC_SEGMENT_HEAD_SIZE); PCLXLGCSegment.wFormat = 0; PCLXLGCSegment.wDefaultGalleyCharacter = 0xFFFF; PCLXLGCSegment.wNumberOfRegions = 0;
//
// NULL Segment initialization
//
PCLXL_NULL_SEGMENT PCLXLNULLSegment;
PCLXLNULLSegment.wSignature = PCLXL_NULL_SIGNATURE; PCLXLNULLSegment.wSegmentSize = 0; PCLXLNULLSegment.wSegmentSizeAlign = 0;
//
// Output
//
*pdwResult = 0; XLOutput *pOutput = pxlpdev->pOutput;
//
// BeginFontHeader
//
pOutput->Send_ubyte(0); pOutput->Send_attr_ubyte(eFontFormat); pOutput->Send_ubyte_array_header(PCLXL_FONTNAME_SIZE); pOutput->Write(PubGetFontName(pdevobj, pUFObj->ulFontID), PCLXL_FONTNAME_SIZE); pOutput->Send_attr_ubyte(eFontName); pOutput->Send_cmd(eBeginFontHeader);
//
// FontHeader
//
uint32 uint32_FontHeaderSize; uint32_FontHeaderSize = sizeof(PCLXLFontHeader); pOutput->Send_uint16((uint16)uint32_FontHeaderSize); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader); pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)uint32_FontHeaderSize); pOutput->Write((PBYTE)&PCLXLFontHeader, uint32_FontHeaderSize);
*pdwResult += sizeof(PCLXLFontHeader);
//
// GT Header
//
uint32_FontHeaderSize = sizeof(PCLXL_GT_SEGMENT); pOutput->Send_uint16((uint16)uint32_FontHeaderSize); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader); pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)uint32_FontHeaderSize); pOutput->Write((PBYTE)&PCLXLGTSegment, uint32_FontHeaderSize);
*pdwResult += sizeof(PCLXL_GT_SEGMENT); //
// TrueType Softfont Directory Header
// Table Dir
//
uint32_FontHeaderSize = sizeof(PCLXL_GT_TABLE_DIR_HEADER); pOutput->Send_uint16((uint16)uint32_FontHeaderSize); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader); pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)uint32_FontHeaderSize); pOutput->Write((PBYTE)&PCLXLDirHeader, sizeof(PCLXLDirHeader));
uint32_FontHeaderSize = sizeof(PCLXL_GT_TABLE_DIR) * dwNumTag; pOutput->Send_uint16((uint16)uint32_FontHeaderSize); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader); pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)uint32_FontHeaderSize); pOutput->Write((PBYTE)PCLXLGTTblDir, sizeof(PCLXL_GT_TABLE_DIR) * dwNumTag);
pOutput->Flush(pdevobj); *pdwResult += sizeof(PCLXL_GT_TABLE_DIR); //
// Table data
//
PBYTE pubData; const BYTE ubNullData[4] = {0, 0, 0, 0}; for (dwI = (USHORT)TagID_First; dwI < (USHORT)TagID_Header; dwI ++) { #if CLASS12
//
// Support only Class 1 and Class 2
//
if (dwI == TagID_hhea || dwI == TagID_hmtx || dwI == TagID_vhea || dwI == TagID_vmtx ) { continue; } #else
//
// Support Class 1 and Class 2 for horizontal font.
// Class 0 for vertical font. PCL XL interpreter doesn't work fine.
//
if (S_OK != pTTFile->IsVertical()) { //
// Support only Class 1 and Class 2
//
if (dwI == TagID_hhea || dwI == TagID_hmtx || dwI == TagID_vhea || dwI == TagID_vmtx ) { continue; } } #endif
//
// Check a table for the tag is available in the TrueType font.
//
tag = TTTag_INVALID; if (S_OK == pTTFile->TagAndID(&dwI, &tag) && S_OK == pTTFile->GetTable(tag, (PVOID*)&pubData, &uint32_FontHeaderSize)) { VERBOSE(("PCLXLDownloadFontHeader:Tag[%d]=%c%c%c%c\n", dwI, 0xff & tag, 0xff & (tag >> 8), 0xff & (tag >> 16), 0xff & (tag >> 24)));
//
// DWORD alignment
//
dwDWAlign = ((uint32_FontHeaderSize + 3) >> 2) << 2;
if (dwDWAlign <= 0x2000) { pOutput->Send_uint16((uint16)(dwDWAlign)); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader);
if (dwDWAlign <= 0xFF) { pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)dwDWAlign); } else { pOutput->WriteByte(PCLXL_dataLength); pOutput->Write((PBYTE)&dwDWAlign, sizeof(uint32)); } pOutput->Write(pubData, uint32_FontHeaderSize); if (uint32_FontHeaderSize = dwDWAlign - uint32_FontHeaderSize) pOutput->Write((PBYTE)ubNullData, uint32_FontHeaderSize); } else { DWORD dwRemain = dwDWAlign; DWORD dwx2000 = 0x2000;
while (dwRemain >= 0x2000) { pOutput->Send_uint16((uint16)0x2000); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader); pOutput->WriteByte(PCLXL_dataLength); pOutput->Write((PBYTE)&dwx2000, sizeof(uint32)); pOutput->Write(pubData, dwx2000); dwRemain -= 0x2000; uint32_FontHeaderSize -= 0x2000; pubData += 0x2000; }
if (dwRemain > 0) { pOutput->Send_uint16((uint16)dwRemain); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader);
if (dwRemain <= 0xFF) { pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)dwRemain); } else { pOutput->WriteByte(PCLXL_dataLength); pOutput->Write((PBYTE)&dwRemain, sizeof(uint32)); } pOutput->Write(pubData, uint32_FontHeaderSize); if (uint32_FontHeaderSize = dwRemain - uint32_FontHeaderSize) pOutput->Write((PBYTE)ubNullData, uint32_FontHeaderSize); } }
*pdwResult += + dwDWAlign; } }
//
// GC segment
//
// Current there is no region.
//
uint32_FontHeaderSize = sizeof(PCLXLGCSegment) - sizeof(PCLXL_GC_REGION); pOutput->Send_uint16((uint16)uint32_FontHeaderSize); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader); pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)uint32_FontHeaderSize); pOutput->Write((PBYTE)&PCLXLGCSegment, uint32_FontHeaderSize);
//
// NULL header
//
uint32_FontHeaderSize = sizeof(PCLXLNULLSegment); pOutput->Send_uint16((uint16)uint32_FontHeaderSize); pOutput->Send_attr_ubyte(eFontHeaderLength); pOutput->Send_cmd(eReadFontHeader); pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)uint32_FontHeaderSize); pOutput->Write((PBYTE)&PCLXLNULLSegment, uint32_FontHeaderSize);
*pdwResult += sizeof(PCLXLNULLSegment);
//
// EndFontHeader
//
pOutput->Send_cmd(eEndFontHeader);
pOutput->Flush(pdevobj);
//
// Download special characters.
//
{ //
// Get glyph data
//
PBYTE pubGlyphData; DWORD dwGlyphDataSize = 0; DWORD dwCompositeDataSize = 0;
if (S_OK != (hResult = pTTFile->GetGlyphData(0, &pubGlyphData, &dwGlyphDataSize))) { ERR(("PCLXL:DownloadFontHeader GetGlyphData failed.\r\n")); return hResult; }
//
// Composte glyph handling.
// http://www.microsoft.com/typography/OTSPEC/glyf.htm
//
// Space character can have data the size of which is ZERO!
// We don't need to return S_FALSE here.
//
BOOL bSpace = FALSE;
if (dwGlyphDataSize != 0 && NULL != pubGlyphData) { #if COMPGLYF
if (((PGLYF)pubGlyphData)->numberOfContours == COMPONENTCTRCOUNT) { dwCompositeDataSize = DwDownloadCompositeGlyph( pdevobj, pUFObj->ulFontID, (PGLYF)pubGlyphData); } #endif
} else { bSpace = TRUE; }
//
// Download actual 0 glyph data
//
if (! BDownloadGlyphData(pdevobj, pUFObj->ulFontID, 0xFFFF, 0, pubGlyphData, dwGlyphDataSize, bSpace)) { ERR(("PCLXL:DownloadCharGlyph BDownloadGlyphData failed.\r\n")); return S_FALSE; }
pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Send_cmd(eEndChar); pOutput->Flush(pdevobj); } } else hResult = S_FALSE;
//
// Add 1 to TrueType font counter.
//
if (hResult == S_OK) { pxlpdev->dwNumOfTTFont ++; } return hResult; }
extern "C" HRESULT APIENTRY PCLXLDownloadCharGlyph( PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, HGLYPH hGlyph, PDWORD pdwWidth, OUT DWORD *pdwResult) /*++
Routine Description:
IPrintOemUni DownloadCharGlyph interface
Arguments:
Return Value:
Note:
--*/ { HRESULT hResult; uint32 uint32_datasize;
VERBOSE(("PCLXLDownloadCharGlyph() entry.\r\n"));
//
// Initialize locals
//
hResult = E_UNEXPECTED; uint32_datasize = 0;
//
// Bitmap font download
//
if (pUFObj->dwFlags & UFOFLAG_TTDOWNLOAD_BITMAP) { VERBOSE(("PCLXLDownloadCharGlyph() BITMAP.\n"));
hResult = S_OK;
//
// Get glyph data
//
GETINFO_GLYPHBITMAP GBmp; GLYPHBITS *pgb; DWORD dwBmpSize; WORD wTopOffset;
GBmp.dwSize = sizeof(GETINFO_GLYPHBITMAP); GBmp.hGlyph = hGlyph; GBmp.pGlyphData = NULL;
if (!pUFObj->pfnGetInfo(pUFObj, UFO_GETINFO_GLYPHBITMAP, &GBmp, 0, NULL)) { ERR(("UNIFONTOBJ_GetInfo:UFO_GETINFO_GLYPHBITMAP failed.\r\n")); return S_FALSE; }
//
// Initalize header
//
PCLXL_BITMAP_CHAR BitmapChar; pgb = GBmp.pGlyphData->gdf.pgb; wTopOffset = (WORD)(- pgb->ptlOrigin.y);
BitmapChar.ubFormat = 0; BitmapChar.ubClass = 0; BitmapChar.wLeftOffset = SWAPW(pgb->ptlOrigin.x); BitmapChar.wTopOffset = SWAPW(wTopOffset); BitmapChar.wCharWidth = SWAPW(pgb->sizlBitmap.cx); BitmapChar.wCharHeight = SWAPW(pgb->sizlBitmap.cy);
dwBmpSize = pgb->sizlBitmap.cy * ((pgb->sizlBitmap.cx + 7) >> 3); uint32_datasize = dwBmpSize + sizeof(BitmapChar);
//
// Output
//
PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM; XLOutput *pOutput = pxlpdev->pOutput;
//
// BeginChar
//
// by GPD
//
// BeginChar
//
if (!(pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON)) { pxlpdev->dwFlags |= XLPDEV_FLAGS_CHARDOWNLOAD_ON;
pOutput->Send_ubyte_array_header(PCLXL_FONTNAME_SIZE); pOutput->Write(PubGetFontName(pdevobj, pUFObj->ulFontID), PCLXL_FONTNAME_SIZE); pOutput->Send_attr_ubyte(eFontName); pOutput->Send_cmd(eBeginChar); }
//
// ReadChar
//
pOutput->Send_uint16((uint16)((PPDEV)pdevobj)->dwNextGlyph); pOutput->Send_attr_ubyte(eCharCode); if (0xFFFF0000 & uint32_datasize) { pOutput->Send_uint32(uint32_datasize); } else if (0x0000FF00) { pOutput->Send_uint16((uint16)uint32_datasize); } else { pOutput->Send_ubyte((ubyte)uint32_datasize); } pOutput->Send_attr_ubyte(eCharDataSize); pOutput->Send_cmd(eReadChar); if (uint32_datasize <= 0xff) { pOutput->WriteByte(PCLXL_dataLengthByte); pOutput->WriteByte((ubyte)uint32_datasize); } else { pOutput->WriteByte(PCLXL_dataLength); pOutput->Write((PBYTE)&uint32_datasize, sizeof(uint32)); } pOutput->Write((PBYTE)&BitmapChar, sizeof(BitmapChar)); pOutput->Flush(pdevobj);
//
// Direct Write
//
WriteSpoolBuf((PPDEV)pdevobj, (PBYTE)pgb->aj, dwBmpSize);
//
// EndChar
// Now EndChar is sent by FlushCachedText
//pOutput->Send_cmd(eEndChar);
pOutput->Flush(pdevobj);
//
// Get fixed pitch TT width
//
pxlpdev->dwFixedTTWidth = (GBmp.pGlyphData->ptqD.x.HighPart + 15) / 16;
//
// Set pdwWidth and pdwResult
//
*pdwWidth = (GBmp.pGlyphData->ptqD.x.HighPart + 15) >> 4;
*pdwResult = (DWORD) uint32_datasize; VERBOSE(("PCLXLDownloadCharGlyph() Width=%d, DataSize=%d\n", *pdwWidth, uint32_datasize)); } else //
// TrueType outline font download
//
if (pUFObj->dwFlags & UFOFLAG_TTDOWNLOAD_TTOUTLINE) { VERBOSE(("PCLXLDownloadCharGlyph() OUTLINE.\n"));
PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM; FONTOBJ *pFontObj;
//
// Get FONTOBJ by calling pUFObj->pfnGetInfo.
//
if (S_OK != GetFONTOBJ(pdevobj, pUFObj, &pFontObj)) { ERR(("PCLXL:DownloadCharGlyph UFO_GETINFO_FONTOBJ failed.\r\n")); return E_UNEXPECTED; }
//
// Open get a pointer to memory-maped TrueType.
//
// ASSUMPTION: pxlpdev->pTTFile is initialized in EnablePDEV.
// The pointer is always available.
//
XLTrueType *pTTFile = pxlpdev->pTTFile; if (S_OK != pTTFile->SameFont(pFontObj)) { pTTFile->OpenTTFile(pFontObj); } else pTTFile = pxlpdev->pTTFile;
//
// Get glyph data
//
PBYTE pubGlyphData; DWORD dwGlyphDataSize = 0; DWORD dwCompositeDataSize = 0;
if (S_OK != (hResult = pTTFile->GetGlyphData(hGlyph, &pubGlyphData, &dwGlyphDataSize))) { ERR(("PCLXL:DownloadCharGlyph GetGlyphData failed.\r\n")); return hResult; }
//
// Composte glyph handling.
// http://www.microsoft.com/typography/OTSPEC/glyf.htm
//
// Space character can have data the size of which is ZERO!
// We don't need to return S_FALSE here.
//
BOOL bSpace;
if (dwGlyphDataSize != 0 && NULL != pubGlyphData) { #if COMPGLYF
if (((PGLYF)pubGlyphData)->numberOfContours == COMPONENTCTRCOUNT) { dwCompositeDataSize = DwDownloadCompositeGlyph( pdevobj, pUFObj->ulFontID, (PGLYF)pubGlyphData); } #endif
bSpace = FALSE; } else { //
// For space character.
//
bSpace = TRUE; }
//
// Download actual hGlyph's glyph data
//
if (! BDownloadGlyphData(pdevobj, pUFObj->ulFontID, ((PDEV*)pdevobj)->dwNextGlyph, hGlyph, pubGlyphData, dwGlyphDataSize, bSpace)) { ERR(("PCLXL:DownloadCharGlyph BDownloadGlyphData failed.\r\n")); if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; XLOutput *pOutput = pxlpdev->pOutput; pOutput->Send_cmd(eEndChar); } return S_FALSE; }
//
// It's Scalable font. We can't get the width.
//
*pdwWidth = 0;
//
// Size of memory to be used.
// There is a case where the size is zero. Add 1 to hack UNIDRV.
//
if (bSpace) { dwGlyphDataSize = 1; }
*pdwResult = (DWORD) dwGlyphDataSize + dwCompositeDataSize;
}
return hResult; }
BOOL BDownloadGlyphData( PDEVOBJ pdevobj, ULONG ulFontID, DWORD dwGlyphID, HGLYPH hGlyph, PBYTE pubGlyphData, DWORD dwGlyphDataSize, BOOL bSpace) { PCLXL_TRUETYPE_CHAR_C0 OutlineCharC0; PCLXL_TRUETYPE_CHAR_C1 OutlineCharC1; PCLXL_TRUETYPE_CHAR_C2 OutlineCharC2; uint32 uint32_datasize;
PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM; XLTrueType *pTTFile = pxlpdev->pTTFile; XLOutput *pOutput = pxlpdev->pOutput;
if (!(pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON)) { pxlpdev->dwFlags |= XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Send_ubyte_array_header(PCLXL_FONTNAME_SIZE); pOutput->Write(PubGetFontName(pdevobj, ulFontID), PCLXL_FONTNAME_SIZE); pOutput->Send_attr_ubyte(eFontName); pOutput->Send_cmd(eBeginChar); }
#if CLASS12
//
// Class 1 for Horizontal font
// Class 2 for Vertical font
//
if (S_OK != pTTFile->IsVertical()) { USHORT usAdvanceWidth; SHORT sLeftSideBearing;
if (S_OK != pTTFile->GetHMTXData(hGlyph, &usAdvanceWidth, &sLeftSideBearing)) { ERR(("PCLXLDownloadFontHeader::GetHMTXData failed.\n")); if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Delete(); } return FALSE; }
//
// The initialization of TrueType Glyphs Format 1 Class 1.
//
uint32_datasize = dwGlyphDataSize + sizeof(OutlineCharC1.wCharDataSize) + sizeof(OutlineCharC1.wLeftSideBearing) + sizeof(OutlineCharC1.wAdvanceWidth) + sizeof(OutlineCharC1.wTrueTypeGlyphID);
OutlineCharC1.ubFormat = 1; OutlineCharC1.ubClass = 1; OutlineCharC1.wCharDataSize = SWAPW((WORD)uint32_datasize); OutlineCharC1.wLeftSideBearing = SWAPW((WORD)sLeftSideBearing); OutlineCharC1.wAdvanceWidth = SWAPW((WORD)usAdvanceWidth); OutlineCharC1.wTrueTypeGlyphID = SWAPW((WORD)hGlyph);
uint32_datasize += sizeof(OutlineCharC1.ubFormat) + sizeof(OutlineCharC1.ubClass);
if (S_OK != pOutput->Send_uint16((uint16)dwGlyphID) || S_OK != pOutput->Send_attr_ubyte(eCharCode) || S_OK != pOutput->Send_uint16((uint16)uint32_datasize) || S_OK != pOutput->Send_attr_ubyte(eCharDataSize) || S_OK != pOutput->Send_cmd(eReadChar)) { if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Delete(); } return FALSE; } } else { USHORT usAdvanceWidth; SHORT sLeftSideBearing; SHORT sTopSideBearing;
if (S_OK != pTTFile->GetVMTXData(hGlyph, &usAdvanceWidth, &sTopSideBearing, &sLeftSideBearing)) { ERR(("PCLXLDownloadCharGlyph::GetVMTXData failed.\n")); if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Delete(); } return FALSE; }
//
// The initialization of TrueType Glyphs Format 1 Class 2.
//
uint32_datasize = dwGlyphDataSize + sizeof(OutlineCharC2.wLeftSideBearing) + sizeof(OutlineCharC2.wTopSideBearing) + sizeof(OutlineCharC2.wAdvanceWidth) + sizeof(OutlineCharC2.wCharDataSize) + sizeof(OutlineCharC2.wTrueTypeGlyphID);
OutlineCharC2.ubFormat = 1; OutlineCharC2.ubClass = 2; OutlineCharC2.wCharDataSize = SWAPW((WORD)uint32_datasize); OutlineCharC2.wLeftSideBearing = SWAPW((WORD)sLeftSideBearing); OutlineCharC2.wAdvanceWidth = SWAPW((WORD)usAdvanceWidth); OutlineCharC2.wTopSideBearing = SWAPW((WORD)sTopSideBearing); OutlineCharC2.wTrueTypeGlyphID = SWAPW((WORD)hGlyph);
uint32_datasize += sizeof(OutlineCharC2.ubFormat) + sizeof(OutlineCharC2.ubClass);
if (S_OK != pOutput->Send_uint16((uint16)dwGlyphID) || S_OK != pOutput->Send_attr_ubyte(eCharCode) || S_OK != pOutput->Send_uint16((uint16)uint32_datasize) || S_OK != pOutput->Send_attr_ubyte(eCharDataSize) || S_OK != pOutput->Send_cmd(eReadChar)) { if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Delete(); } return FALSE; } } #else{
//
// The initialization of TrueType Glyphs Format 1 Class 0.
//
uint32_datasize = dwGlyphDataSize + sizeof(OutlineCharC0.wCharDataSize) + sizeof(OutlineCharC0.wTrueTypeGlyphID);
OutlineCharC0.ubFormat = 1; OutlineCharC0.ubClass = 0; OutlineCharC0.wCharDataSize = SWAPW((WORD)uint32_datasize); OutlineCharC0.wTrueTypeGlyphID = SWAPW((WORD)hGlyph);
uint32_datasize += sizeof(OutlineCharC0.ubFormat) + sizeof(OutlineCharC0.ubClass);
if (S_OK != pOutput->Send_uint16((uint16)dwGlyphID) || S_OK != pOutput->Send_attr_ubyte(eCharCode) || S_OK != pOutput->Send_uint16((uint16)uint32_datasize) || S_OK != pOutput->Send_attr_ubyte(eCharDataSize) || S_OK != pOutput->Send_cmd(eReadChar)) { if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Delete(); } return FALSE; } } #endif
if (uint32_datasize <= 0xff) { if (S_OK != pOutput->WriteByte(PCLXL_dataLengthByte) || S_OK != pOutput->WriteByte((ubyte)uint32_datasize)) { if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Delete(); } return FALSE; } } else { if (S_OK != pOutput->WriteByte(PCLXL_dataLength) || S_OK != pOutput->Write((PBYTE)&uint32_datasize, sizeof(uint32))) { if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Delete(); } return FALSE; } }
#if CLASS12
if (S_OK != pTTFile->IsVertical()) { pOutput->Write((PBYTE)&OutlineCharC1, sizeof(OutlineCharC1)); } else { pOutput->Write((PBYTE)&OutlineCharC2, sizeof(OutlineCharC2)); } #else
pOutput->Write((PBYTE)&OutlineCharC0, sizeof(OutlineCharC0)); #endif
if (S_OK == pOutput->Flush(pdevobj)) { if (!bSpace) { //
// Direct Write
//
dwGlyphDataSize = (DWORD)WriteSpoolBuf((PPDEV)pdevobj, pubGlyphData, dwGlyphDataSize); } return TRUE; } else { if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Delete(); } return FALSE; } }
extern "C" HRESULT APIENTRY PCLXLTTDownloadMethod( PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, OUT DWORD *pdwResult) /*++
Routine Description:
IPrintOemUni TTDownloadMethod interface
Arguments:
Return Value:
Note:
--*/ { VERBOSE(("PCLXLTTDownloadMethod() entry.\r\n"));
//
// Error Check
//
if (NULL == pdevobj || NULL == pUFObj || NULL == pUFObj->pIFIMetrics || NULL == pdwResult ) { ERR(("PCLXLTTDownloadMethod(): invalid parameters.\r\n")); return E_UNEXPECTED; }
//
// Initialize
//
*pdwResult = TTDOWNLOAD_GRAPHICS;
if (((PPDEV)pdevobj)->pGlobals->fontformat == UNUSED_ITEM) { //
// There is no font download format specified.
// Prints as graphics.
//
return S_OK; }
//
// Return GRAPHICS for non-TrueType font
//
if ( !(pUFObj->pIFIMetrics->flInfo & FM_INFO_TECH_TRUETYPE) ) { ERR(("PCLXLTTDownloadMethod(): invalid font.\r\n")); return S_OK; }
//
// Text As Graphics
//
if (((PPDEV)pdevobj)->pdmPrivate->dwFlags & DXF_TEXTASGRAPHICS) { return S_OK; }
//
// Get XForm and X and Y scaling factors.
//
PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM; FLOATOBJ_XFORM xform; FLOATOBJ foXScale, foYScale;
if (S_OK != GetXForm(pdevobj, pUFObj, &xform) || S_OK != GetXYScale(&xform, &foXScale, &foYScale)) { ERR(("PCLXLTTDownloadMethod(): Failed to get X and Y Scale.\r\n")); return E_UNEXPECTED; } //
// Scale fwdUnitsPerEm
//
FLOATOBJ_MulLong(&foYScale, pUFObj->pIFIMetrics->fwdUnitsPerEm); FLOATOBJ_MulLong(&foXScale, pUFObj->pIFIMetrics->fwdUnitsPerEm); pxlpdev->fwdUnitsPerEm = (FWORD)FLOATOBJ_GetLong(&foYScale); pxlpdev->fwdMaxCharWidth = (FWORD)FLOATOBJ_GetLong(&foXScale);
//
// Download as Bitmap softfont
//
if (((PPDEV)pdevobj)->pGlobals->fontformat == FF_HPPCL || ((PPDEV)pdevobj)->pGlobals->fontformat == FF_HPPCL_RES) { *pdwResult = TTDOWNLOAD_BITMAP; return S_OK; }
//
// Parse TrueType font
//
XLTrueType *pTTFile = pxlpdev->pTTFile; FONTOBJ *pFontObj;
if (S_OK == GetFONTOBJ(pdevobj, pUFObj, &pFontObj)) { if (S_OK != pTTFile->OpenTTFile(pFontObj)) { ERR(("PCLXL:TTDownloadMethod(): Failed to open TT file.\n")); return S_FALSE; } }
//
// Reverse width and height, if the font is a vertial font.
//
if (S_OK == pTTFile->IsVertical()) { FWORD fwdTmp; fwdTmp = pxlpdev->fwdUnitsPerEm; pxlpdev->fwdUnitsPerEm = pxlpdev->fwdMaxCharWidth; pxlpdev->fwdMaxCharWidth = fwdTmp; }
//
// Always return TrueType Outline
//
*pdwResult = TTDOWNLOAD_TTOUTLINE;
VERBOSE(("PCLXLTTDownloadMethod() pdwResult=%d\n", *pdwResult)); return S_OK; }
extern "C" HRESULT APIENTRY PCLXLOutputCharStr( PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, DWORD dwType, DWORD dwCount, PVOID pGlyph) /*++
Routine Description:
IPrintOemUni OutputCharStr interface
Arguments:
Return Value:
Note:
--*/ { PXLPDEV pxlpdev;
//
// UNIFONTOBJ callback data structures
//
GETINFO_GLYPHSTRING GStr; GETINFO_GLYPHWIDTH GWidth;
//
// Device font TRANSDATA structure
//
PTRANSDATA pTransOrg, pTrans;
PPOINTL pptlCharAdvance; PWORD pawChar;
PLONG plWidth; DWORD dwGetInfo, dwI, dwcbInitSize;
VERBOSE(("PCLXLOutputCharStr() entry.\r\n"));
//
// Error parameter check
//
if (0 == dwCount || NULL == pGlyph || NULL == pUFObj ) { ERR(("PCLXLOutptuChar: Invalid parameters\n")); return E_UNEXPECTED; }
pxlpdev= (PXLPDEV)pdevobj->pdevOEM;
//
// Get current text resolution
//
if (pxlpdev->dwTextRes == 0) { GETINFO_STDVAR StdVar; DWORD dwSizeNeeded;
StdVar.dwSize = sizeof(GETINFO_STDVAR); StdVar.dwNumOfVariable = 1; StdVar.StdVar[0].dwStdVarID = FNT_INFO_TEXTYRES; StdVar.StdVar[0].lStdVariable = 0; pUFObj->pfnGetInfo(pUFObj, UFO_GETINFO_STDVARIABLE, &StdVar, StdVar.dwSize, &dwSizeNeeded);
pxlpdev->dwTextRes = StdVar.StdVar[0].lStdVariable; }
//
// Allocate memory for character cache
//
if (0 == pxlpdev->dwMaxCharCount || pxlpdev->dwMaxCharCount < pxlpdev->dwCharCount + dwCount) { DWORD dwInitCount = INIT_CHAR_NUM;
//
// Calculate the initial data size
//
if (dwInitCount < pxlpdev->dwCharCount + dwCount) { dwInitCount = pxlpdev->dwCharCount + dwCount; }
//
// Allocate memory
//
if (!(pptlCharAdvance = (PPOINTL)MemAlloc(sizeof(POINTL) * dwInitCount)) || !(pawChar = (PWORD)MemAlloc(sizeof(WORD) * dwInitCount)) ) { ERR(("PCLXL:CharWidth buffer allocation failed.\n")); if (pptlCharAdvance) { MemFree(pptlCharAdvance); } return E_UNEXPECTED; }
//
// Copy the old buffer to new buffer
//
if (pxlpdev->dwCharCount > 0) { CopyMemory(pptlCharAdvance, pxlpdev->pptlCharAdvance, pxlpdev->dwCharCount * sizeof(POINTL)); CopyMemory(pawChar, pxlpdev->pawChar, pxlpdev->dwCharCount * sizeof(WORD)); }
if (pxlpdev->pptlCharAdvance) MemFree(pxlpdev->pptlCharAdvance); if (pxlpdev->pawChar) MemFree(pxlpdev->pawChar);
pxlpdev->pptlCharAdvance = pptlCharAdvance; pxlpdev->pawChar = pawChar; pxlpdev->dwMaxCharCount = dwInitCount; }
XLOutput *pOutput = pxlpdev->pOutput;
//
// Y cursor position is different from the previous OutputCharGlyph
// Flush the string cache
//
if (0 == pxlpdev->dwCharCount) { pxlpdev->lStartX = pxlpdev->lX = ((TO_DATA*)((PFONTPDEV)pxlpdev->pPDev->pFontPDev)->ptod)->ptlFirstGlyph.x; pxlpdev->lStartY = pxlpdev->lY = ((TO_DATA*)((PFONTPDEV)pxlpdev->pPDev->pFontPDev)->ptod)->ptlFirstGlyph.y;
if (((TO_DATA*)((PFONTPDEV)pxlpdev->pPDev->pFontPDev)->ptod)->iRot) { pxlpdev->dwTextAngle = ((TO_DATA*)((PFONTPDEV)pxlpdev->pPDev->pFontPDev)->ptod)->iRot; } }
//
// Init pawChar
//
pawChar = pxlpdev->pawChar + pxlpdev->dwCharCount;
switch(dwType) { case TYPE_GLYPHHANDLE: //
// Get TRANSDATA
//
GStr.dwSize = sizeof(GETINFO_GLYPHSTRING); GStr.dwCount = dwCount; GStr.dwTypeIn = TYPE_GLYPHHANDLE; GStr.pGlyphIn = pGlyph; GStr.dwTypeOut = TYPE_TRANSDATA; GStr.pGlyphOut = NULL; GStr.dwGlyphOutSize = 0;
dwGetInfo = GStr.dwSize;
//
// Get necessary buffer size
//
pUFObj->pfnGetInfo(pUFObj, UFO_GETINFO_GLYPHSTRING, &GStr, dwGetInfo, &dwGetInfo);
if (!GStr.dwGlyphOutSize) { ERR(("PCLXLOutptuChar: GetInfo( 1st GLYPHSTRING) failed\n")); return E_UNEXPECTED; }
if (NULL == pxlpdev->pTransOrg || dwCount * sizeof(TRANSDATA) > pxlpdev->dwcbTransSize || GStr.dwGlyphOutSize > pxlpdev->dwcbTransSize) { dwcbInitSize = INIT_CHAR_NUM * sizeof(TRANSDATA); if (dwcbInitSize < GStr.dwGlyphOutSize) { dwcbInitSize = GStr.dwGlyphOutSize; } if (dwcbInitSize < dwCount * sizeof(TRANSDATA)) { dwcbInitSize = dwCount * sizeof(TRANSDATA); }
if (NULL == pxlpdev->pTransOrg) { MemFree(pxlpdev->pTransOrg); } if ((pTransOrg = (PTRANSDATA)MemAlloc(dwcbInitSize)) == NULL) { ERR(("PCLXLOutptuChar: MemAlloc failed\n")); return E_UNEXPECTED; } pxlpdev->pTransOrg = pTransOrg; pxlpdev->dwcbTransSize = dwcbInitSize; } else { pTransOrg = pxlpdev->pTransOrg; }
GStr.pGlyphOut = (PVOID)pTransOrg;
if (!pUFObj->pfnGetInfo(pUFObj, UFO_GETINFO_GLYPHSTRING, &GStr, dwGetInfo, &dwGetInfo)) { ERR(("PCLXLOutptuChar: GetInfo( 2nd GLYPHSTRING) failed\n")); return E_UNEXPECTED; }
pTrans = pTransOrg;
for (dwI = 0; dwI < dwCount; dwI++, pTrans++) { switch(pTrans->ubType & MTYPE_FORMAT_MASK) { case MTYPE_COMPOSE: ERR(("PCLXL:OutputCharGlyph: Unsupported ubType\n")); break; case MTYPE_DIRECT: VERBOSE(("PCLXLOutputCharStr:%c\n", pTrans->uCode.ubCode)); *pawChar++ = pTrans->uCode.ubCode; break; case MTYPE_PAIRED: *pawChar++ = *(PWORD)(pTrans->uCode.ubPairs); break; } } break;
case TYPE_GLYPHID: for (dwI = 0; dwI < dwCount; dwI++, pawChar++) { CopyMemory(pawChar, (PDWORD)pGlyph + dwI, sizeof(WORD)); } break; }
//
// Get Character width
//
//
// Store char position info
//
pptlCharAdvance = pxlpdev->pptlCharAdvance + pxlpdev->dwCharCount;
//
// dwCharCount holds the number of chars in the character cache
// dwCharCount = 0: Store start X pos
// Current Y pos
//
if (pxlpdev->dwCharCount == 0) { //
// UNIDRV hack
// Get the first character position.
//
pxlpdev->lPrevX = pxlpdev->lStartX = pxlpdev->lX = ((TO_DATA*)((PFONTPDEV)pxlpdev->pPDev->pFontPDev)->ptod)->ptlFirstGlyph.x; pxlpdev->lPrevY = pxlpdev->lStartY = pxlpdev->lY = ((TO_DATA*)((PFONTPDEV)pxlpdev->pPDev->pFontPDev)->ptod)->ptlFirstGlyph.y; VERBOSE(("PCLXLOutputCharStr: %d",pxlpdev->lStartX)); }
GLYPHPOS *pgp = ((TO_DATA*)((PFONTPDEV)pxlpdev->pPDev->pFontPDev)->ptod)->pgp;
if (pxlpdev->dwCharCount > 0) { if (pxlpdev->dwCharCount < ((TO_DATA*)((PFONTPDEV)pxlpdev->pPDev->pFontPDev)->ptod)->cGlyphsToPrint) { pgp += pxlpdev->dwCharCount; }
(pptlCharAdvance - 1)->x = pgp->ptl.x - pxlpdev->lPrevX; (pptlCharAdvance - 1)->y = pgp->ptl.y - pxlpdev->lPrevY; }
for (dwI = 0; dwI < dwCount - 1; dwI ++, pptlCharAdvance ++, pgp ++) { pptlCharAdvance->x = pgp[1].ptl.x - pgp->ptl.x; pptlCharAdvance->y = pgp[1].ptl.y - pgp->ptl.y; VERBOSE((",(%d, %d)", pptlCharAdvance->x, pptlCharAdvance->y)); } VERBOSE(("\n"));
pptlCharAdvance->x = pptlCharAdvance->y = 0; pxlpdev->lPrevX = pgp->ptl.x; pxlpdev->lPrevY = pgp->ptl.y; pxlpdev->dwCharCount += dwCount;
return S_OK; }
extern "C" HRESULT APIENTRY PCLXLSendFontCmd( PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, PFINVOCATION pFInv) /*++
Routine Description:
IPrintOemUni SendFontCmd interface
Arguments:
Return Value:
Note:
--*/ { VERBOSE(("PCLXLSendFontCmd() entry.\r\n"));
CHAR cSymbolSet[16]; PBYTE pubCmd;
if (NULL == pFInv || NULL == pFInv->pubCommand || 0 == pFInv->dwCount ) { VERBOSE(("PCLXLSendFontCmd: unexpected FINVOCATION\n")); return S_OK; }
PXLPDEV pxlpdev = (PXLPDEV)pdevobj->pdevOEM; XLOutput *pOutput = pxlpdev->pOutput;
if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Send_cmd(eEndChar); }
if (pUFObj->dwFlags & UFOFLAG_TTFONT) { if (pFInv->dwCount == sizeof(DWORD)) { if (pUFObj->dwFlags & UFOFLAG_TTDOWNLOAD_BITMAP) { pOutput->SetFont(kFontTypeTTBitmap, PubGetFontName(pdevobj, pUFObj->ulFontID), pxlpdev->fwdUnitsPerEm, pxlpdev->fwdMaxCharWidth, 0x0002, (DWORD)0); } else { DWORD dwFontSimulation = pUFObj->dwFlags & (UFOFLAG_TTOUTLINE_BOLD_SIM|UFOFLAG_TTOUTLINE_ITALIC_SIM|UFOFLAG_TTOUTLINE_VERTICAL);
//
// UFOFLAG_TTOUTLINE_BOLD_SIM = 0x08
// UFOFLAG_TTOUTLINE_ITALIC_SIM = 0x10
// UFOFLAG_TTOUTLINE_VERTICAL = 0x20
//
// XLOUTPUT_FONTSIM_BOLD = 0x01
// XLOUTPUT_FONTSIM_ITALIC = 0x02
// XLOUTPUT_FONTSIM_VERTICAL = 0x03
//
dwFontSimulation >>= 3;
pOutput->SetFont(kFontTypeTTOutline, PubGetFontName(pdevobj, pUFObj->ulFontID), pxlpdev->fwdUnitsPerEm, pxlpdev->fwdMaxCharWidth, 0x0002, dwFontSimulation); } } else { VERBOSE(("PCLXLSendFontCmd: unexpected FINVOCATION\n")); return S_FALSE; } } else { DWORD dwSizeNeeded, dwSize, dwSymbolSet;
pubCmd = pFInv->pubCommand; pubCmd += pFInv->dwCount; pubCmd --;
//
// Get a symbol set
//
// ASSUMPTION: Font selecton string is like following!!!!
//
// "Courier 590"
// 12345678901234567890
// the size of font name is 16. Plus space and symbol set number.
//
if (pFInv->dwCount < 0x11) { ERR(("PCLXL:SendFontCmd: Invalid font selection command.\n")); return E_UNEXPECTED; }
dwSize = 0; while (*pubCmd != 0x20 && dwSize < pFInv->dwCount) { pubCmd--; dwSize ++; }
if (dwSize != 0) { pubCmd++; CopyMemory(cSymbolSet, pubCmd, dwSize); } cSymbolSet[dwSize] = NULL;
dwSymbolSet = (DWORD)atoi(cSymbolSet);
//
// Get FONTOBJ
//
FONTOBJ *pFontObj; GetFONTOBJ(pdevobj, pUFObj, &pFontObj);
//
// Get XForm
//
FLOATOBJ foXScale, foYScale; FLOATOBJ_XFORM xform;
if (S_OK != GetXForm(pdevobj, pUFObj, &xform) || S_OK != GetXYScale(&xform, &foXScale, &foYScale)) { return E_UNEXPECTED; }
//
// Scale Height and Width
//
// Is X scaled differently from Y?
// If so, set X.
//
DWORD dwFontWidth; FLOATOBJ_MulLong(&foYScale, pUFObj->pIFIMetrics->fwdUnitsPerEm); FLOATOBJ_MulLong(&foXScale, pUFObj->pIFIMetrics->fwdUnitsPerEm); pxlpdev->dwFontHeight = (FWORD)FLOATOBJ_GetLong(&foYScale); pxlpdev->dwFontWidth = (FWORD)FLOATOBJ_GetLong(&foXScale); if (S_OK == IsXYSame(&xform)) { dwFontWidth = 0; } else { dwFontWidth = pxlpdev->dwFontWidth; }
BYTE aubFontName[PCLXL_FONTNAME_SIZE + 1]; CopyMemory(aubFontName, pFInv->pubCommand, PCLXL_FONTNAME_SIZE); aubFontName[PCLXL_FONTNAME_SIZE] = NULL; pOutput->SetFont(kFontTypeDevice, (PBYTE)aubFontName, pxlpdev->dwFontHeight, dwFontWidth, dwSymbolSet, 0); }
pOutput->Flush(pdevobj);
if (pxlpdev->dwFlags & XLPDEV_FLAGS_RESET_FONT) { BSaveFont(pdevobj); }
return S_OK; }
HRESULT FlushCachedText( PDEVOBJ pdevobj) /*++
Routine Description:
Arguments:
Return Value:
Note:
--*/ { PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM; DWORD dwI;
VERBOSE(("PCLXLFlushCachedText: Flush cached characters:%d\r\n", pxlpdev->dwCharCount));
if (pxlpdev->dwCharCount == 0) return S_OK;
XLOutput *pOutput = pxlpdev->pOutput;
PWORD pawChar = pxlpdev->pawChar; PPOINTL pptlCharAdvance = pxlpdev->pptlCharAdvance;
sint16 sint16_advance; ubyte ubyte_advance;
XLGState *pGState = pxlpdev->pOutput;
if (pxlpdev->dwFlags & XLPDEV_FLAGS_CHARDOWNLOAD_ON) { pxlpdev->dwFlags &= ~XLPDEV_FLAGS_CHARDOWNLOAD_ON; pOutput->Send_cmd(eEndChar); }
//
// Flush cached char string
//
//
// Reselect font
//
if (pxlpdev->dwFlags & XLPDEV_FLAGS_RESET_FONT) { BYTE aubFontName[PCLXL_FONTNAME_SIZE + 1];
VERBOSE(("PCLXLFlushCachedText: ResetFont\n"));
pxlpdev->dwFlags &= ~XLPDEV_FLAGS_RESET_FONT; pxlpdev->pXLFont->GetFontName(aubFontName); pOutput->SetFont(pxlpdev->pXLFont->GetFontType(), aubFontName, pxlpdev->pXLFont->GetFontHeight(), pxlpdev->pXLFont->GetFontWidth(), pxlpdev->pXLFont->GetFontSymbolSet(), pxlpdev->pXLFont->GetFontSimulation()); }
//
// Set cursor
//
pOutput->SetCursor(pxlpdev->lStartX, pxlpdev->lStartY);
//
// Set text angle
//
if (pxlpdev->dwTextAngle && kFontTypeTTBitmap != pGState->GetFontType()) { pOutput->Send_uint16((uint16)pxlpdev->dwTextAngle); pOutput->Send_attr_ubyte(eCharAngle); pOutput->Send_cmd(eSetCharAngle); }
//
// Characters
//
pOutput->Send_uint16_array_header((uint16)pxlpdev->dwCharCount); VERBOSE(("String = ")); for (dwI = 0; dwI < pxlpdev->dwCharCount; dwI ++, pawChar++) { pOutput->Write((PBYTE)pawChar, sizeof(WORD)); VERBOSE(("0x%x ", *pawChar)); } VERBOSE(("\r\n")); pOutput->Send_attr_ubyte(eTextData);
//
// X advance
//
VERBOSE(("Advance(0x%x)(x,y) = (%d,%d),", pptlCharAdvance, pptlCharAdvance->x, pptlCharAdvance->y));
BOOL bXUByte = TRUE; BOOL bYUByte = TRUE; BOOL bXAdvanceTrue = FALSE; BOOL bYAdvanceTrue = FALSE; for (dwI = 0; dwI < pxlpdev->dwCharCount; dwI ++, pptlCharAdvance++) { //
// If the char advance is ubyte, set bUByte flag to optimize XSpacing
//
if (pptlCharAdvance->x & 0xffffff00) bXUByte = FALSE; if (pptlCharAdvance->y & 0xffffff00) bYUByte = FALSE; if (pptlCharAdvance->x != 0) bXAdvanceTrue = TRUE; if (pptlCharAdvance->y != 0) bYAdvanceTrue = TRUE; }
//
// X Advance
//
if (bXAdvanceTrue) { pptlCharAdvance = pxlpdev->pptlCharAdvance;
VERBOSE(("X = ")); if (bXUByte == TRUE) { //
// ubyte XSpacing
//
pOutput->Send_ubyte_array_header((uint16)pxlpdev->dwCharCount);
for (dwI = 0; dwI < pxlpdev->dwCharCount; dwI ++, pptlCharAdvance++) { ubyte_advance = (ubyte)pptlCharAdvance->x; pOutput->Write((PBYTE)&ubyte_advance, sizeof(ubyte)); #if DBG
VERBOSE(("%d ", ubyte_advance)); if (0 == ubyte_advance) { VERBOSE(("\nXSpacing is zero!.\n")); } #endif
} } else { //
// sint16 XSpacing
//
pOutput->Send_sint16_array_header((uint16)pxlpdev->dwCharCount);
for (dwI = 0; dwI < pxlpdev->dwCharCount; dwI ++, pptlCharAdvance++) { sint16_advance = (sint16)pptlCharAdvance->x; pOutput->Write((PBYTE)&sint16_advance, sizeof(sint16)); #if DBG
VERBOSE(("%d ", sint16_advance)); if (0 == sint16_advance) { VERBOSE(("\nXSpacing is zero!.\n")); } #endif
} }
VERBOSE(("\r\n")); pOutput->Send_attr_ubyte(eXSpacingData); } //
// Y Advance
//
if (bYAdvanceTrue) { pptlCharAdvance = pxlpdev->pptlCharAdvance;
VERBOSE(("Y = ")); if (bYUByte == TRUE) { //
// ubyte YSpacing
//
pOutput->Send_ubyte_array_header((uint16)pxlpdev->dwCharCount);
for (dwI = 0; dwI < pxlpdev->dwCharCount; dwI ++, pptlCharAdvance++) { ubyte_advance = (ubyte)pptlCharAdvance->y; pOutput->Write((PBYTE)&ubyte_advance, sizeof(ubyte)); #if DBG
VERBOSE(("%d ", ubyte_advance)); if (0 == ubyte_advance) { VERBOSE(("\nYSpacing is zero!.\n")); } #endif
} } else { //
// sint16 YSpacing
//
pOutput->Send_sint16_array_header((uint16)pxlpdev->dwCharCount);
for (dwI = 0; dwI < pxlpdev->dwCharCount; dwI ++, pptlCharAdvance++) { sint16_advance = (sint16)pptlCharAdvance->y; pOutput->Write((PBYTE)&sint16_advance, sizeof(sint16)); #if DBG
VERBOSE(("%d ", sint16_advance)); if (0 == sint16_advance) { VERBOSE(("\nYSpacing is zero!.\n")); } #endif
} }
VERBOSE(("\r\n")); pOutput->Send_attr_ubyte(eYSpacingData); }
pOutput->Send_cmd(eText);
//
// Reset text angle
//
if (pxlpdev->dwTextAngle && kFontTypeTTBitmap != pGState->GetFontType()) { pOutput->Send_uint16(0); pOutput->Send_attr_ubyte(eCharAngle); pOutput->Send_cmd(eSetCharAngle); pxlpdev->dwTextAngle = 0; }
pOutput->Flush(pdevobj);
pxlpdev->dwCharCount = 0;
return S_OK; }
HRESULT GetFONTOBJ( PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, FONTOBJ **ppFontObj) /*++
Routine Description:
Arguments:
Return Value:
Note:
--*/ { //
// Error Check
//
if (NULL == ppFontObj || pdevobj->dwSize != sizeof(DEVOBJ) ) { ERR(("PCLXL:GetFONTOBJ: invalid parameter[s].\n")); return E_UNEXPECTED; }
PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM; DWORD dwGetInfo; GETINFO_FONTOBJ GFontObj;
dwGetInfo = GFontObj.dwSize = sizeof(GETINFO_FONTOBJ); GFontObj.pFontObj = NULL;
if (!pUFObj->pfnGetInfo(pUFObj, UFO_GETINFO_FONTOBJ, &GFontObj, dwGetInfo, &dwGetInfo)) { ERR(("PCLXL:GetXForm: GetInfo(FONTOBJ) failed\n")); return E_UNEXPECTED; }
*ppFontObj = GFontObj.pFontObj; return S_OK; }
HRESULT GetXForm( PDEVOBJ pdevobj, PUNIFONTOBJ pUFObj, FLOATOBJ_XFORM* pxform) /*++
Routine Description:
Arguments:
Return Value:
Note:
--*/ { //
// Error Check
//
if (NULL == pxform || NULL == pdevobj || pdevobj->dwSize != sizeof(DEVOBJ) ) { ERR(("PCLXL:GetXForm: invalid parameter[s].\n")); return E_UNEXPECTED; }
FONTOBJ *pFontObj; if (S_OK != GetFONTOBJ(pdevobj, pUFObj, &pFontObj)) { ERR(("PCLXL:GetXForm: GetFONTOBJ failed.\n")); return E_UNEXPECTED; }
XFORMOBJ *pxo = FONTOBJ_pxoGetXform(pFontObj); XFORMOBJ_iGetFloatObjXform(pxo, pxform);
return S_OK; }
HRESULT GetXYScale( FLOATOBJ_XFORM *pxform, FLOATOBJ *pfoXScale, FLOATOBJ *pfoYScale) /*++
Routine Description:
Arguments:
Return Value:
Note:
--*/ { //
// Error Check
//
if (NULL == pxform || NULL == pfoXScale || NULL == pfoYScale ) { ERR(("PCLXL:GetXYScale: invalid parameter[s].\n")); return E_UNEXPECTED; }
#if 0
if( pxform->eM11 ) { //
// Either 0 or 180 rotation
//
if( pxform->eM11 > 0 ) { //
// Normal case, 0 degree rotation
//
*pfoXScale = pxform->eM11; *pfoYScale = pxform->eM22; } else { //
// Reverse case, 180 degree rotation
//
*pfoXScale = -pxform->eM11; *pfoYScale = -pxform->eM22; } } else { //
// Must be 90 or 270 degree rotation
//
if( pxform->eM12 < 0 ) { //
// The 90 degree case
//
*pfoXScale = pxform->eM21; *pfoYScale = -pxform->eM12; } else { //
// The 270 degree case
//
*pfoXScale = -pxform->eM21; *pfoYScale = pxform->eM12; } } #else
if (pxform->eM21 == 0 && pxform->eM12 == 0) { //
// 0 or 180 degree rotation
//
if( pxform->eM11 > 0 ) { //
// The 0 degree case
//
*pfoXScale = pxform->eM11; *pfoYScale = pxform->eM22; } else { //
// The 180 degree case
//
*pfoXScale = -pxform->eM11; *pfoYScale = -pxform->eM22; } } else if (pxform->eM11 == 0 && pxform->eM22 == 0) { //
// Must be 90 or 270 degree rotation
//
if( pxform->eM21 < 0 ) { //
// The 90 degree case
//
*pfoXScale = -pxform->eM21; *pfoYScale = pxform->eM12; } else { //
// The 270 degree case
//
*pfoXScale = pxform->eM21; *pfoYScale = -pxform->eM12; } } else { #pragma warning( disable: 4244)
*pfoXScale = sqrt(pxform->eM11 * pxform->eM11 + pxform->eM12 * pxform->eM12); *pfoYScale = sqrt(pxform->eM22 * pxform->eM22 + pxform->eM21 * pxform->eM21); #pragma warning( default: 4244)
} #endif
return S_OK; }
HRESULT IsXYSame( FLOATOBJ_XFORM *pxform) /*++
Routine Description:
Arguments:
Return Value:
Note:
--*/ { BOOL bRet; FLOATOBJ eM11 = pxform->eM11;
if (FLOATOBJ_EqualLong(&eM11, 0)) { return S_OK; }
//
// 0-90 or 180-270 case
// (eM11 > 0 & eM22 > 0)
// (eM12 < 0 & eM21 < 0)
//
// eM11 = (eM11 - eM22) / eM11;
//
FLOATOBJ_Sub(&(eM11), &(pxform->eM22)); FLOATOBJ_Div(&(eM11), &(pxform->eM11));
//
// eM11 < 0.5%
//
bRet = FLOATOBJ_LessThanLong(&(eM11), FLOATL_IEEE_0_005F) & FLOATOBJ_GreaterThanLong(&(eM11), FLOATL_IEEE_0_005MF);
if (!bRet) { //
// 90-180 or 270-360 case
// (eM11 < 0, eM22 > 0)
// (eM11 > 0, eM22 < 0)
//
// eM11 = (eM11 + eM22) / eM11;
//
eM11 = pxform->eM11; FLOATOBJ_Add(&(eM11), &(pxform->eM22)); FLOATOBJ_Div(&(eM11), &(pxform->eM11));
//
// eM11 < 0.5%
//
bRet = FLOATOBJ_LessThanLong(&(eM11), FLOATL_IEEE_0_005F) & FLOATOBJ_GreaterThanLong(&(eM11), FLOATL_IEEE_0_005MF); }
if (bRet) return S_OK; else return S_FALSE; }
DWORD DwDownloadCompositeGlyph( PDEVOBJ pdevobj, ULONG ulFontID, PGLYF pGlyph) /*++
Routine Description:
Download composite glyph data. Arguments:
pdevobj - a pointer to PDEVOBJ ulFontID - font ID for this glyph. pGlyph - a pointer to GLYF data structure.
Return Value:
Note:
--*/ { PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM; XLTrueType *pTTFile = pxlpdev->pTTFile;
PBYTE pubCGlyphData = (PBYTE)pGlyph; DWORD dwCGlyphDataSize, dwRet;
dwRet = 0;
if (pGlyph->numberOfContours != COMPONENTCTRCOUNT) { //
// Error check. Make sure that this is a composite glyph.
//
return dwRet; }
//
// According to TrueType font spec, if numberOfContours == -1,
// it has composite glyph data.
//
// When downloading special glyphs, specify the value 0xFFFF for the
// CharCode attribute to the ReadChar operator.
// This "special" CharCode value tells PCL XL 2.0 that
// it is a "special" glyph.
//
// pCGlyf points an array of CGLYF. pCGlyf->flags says that there is
// at least one more composite glyph available.
// I need to go through all glyph data.
//
PCGLYF pCGlyf = (PCGLYF)(pubCGlyphData + sizeof(GLYF)); SHORT sFlags; BOOL bSpace;
do { //
// Swap bytes in any date in TrueType font, since it's Motorola-style ordering (Big Endian).
//
sFlags = SWAPW(pCGlyf->flags);
//
// Get glyph data from TrueType font object.
//
if (S_OK != pTTFile->GetGlyphData( SWAPW(pCGlyf->glyphIndex), &pubCGlyphData, &dwCGlyphDataSize)) { ERR(("PCLXL:DownloadCharGlyph GetGlyphData failed.\r\n")); return FALSE; }
if (NULL != pubCGlyphData && dwCGlyphDataSize != 0) { if (((PGLYF)pubCGlyphData)->numberOfContours == COMPONENTCTRCOUNT) { //
// A recursive call to DwDownloadCompositeGlyph for this glyph.
//
dwRet += DwDownloadCompositeGlyph(pdevobj, ulFontID, (PGLYF)pubCGlyphData); }
bSpace = FALSE; } else { bSpace = TRUE; }
//
// Download the actual glyph data for this glyph with 0xFFFF.
// Special character (PCL XL 2.0)
//
if (!BDownloadGlyphData(pdevobj, ulFontID, 0xFFFF, SWAPW(pCGlyf->glyphIndex), pubCGlyphData, dwCGlyphDataSize, bSpace)) { ERR(("PCLXL:DownloadCharGlyph BDownloadGlyphData failed.\r\n")); return dwRet; }
dwRet += dwCGlyphDataSize;
//
// If ARG_1_AND_2_ARE_WORDS is set, the arguments are words.
// Otherwise, they are bytes.
//
PBYTE pByte = (PBYTE)pCGlyf; if (sFlags & ARG_1_AND_2_ARE_WORDS) { pByte += sizeof(CGLYF); } else { pByte += sizeof(CGLYF_BYTE); }
pCGlyf = (PCGLYF)pByte;
} while (sFlags & MORE_COMPONENTS);
return dwRet; }
inline BOOL BSaveFont( PDEVOBJ pdevobj) { PXLPDEV pxlpdev= (PXLPDEV)pdevobj->pdevOEM; pxlpdev->dwFlags |= XLPDEV_FLAGS_RESET_FONT;
if (NULL == pxlpdev->pXLFont) { pxlpdev->pXLFont = new XLFont; if (NULL == pxlpdev->pXLFont) { return FALSE; } }
XLGState *pGState = pxlpdev->pOutput; BYTE aubFontName[PCLXL_FONTNAME_SIZE + 1];
pGState->GetFontName(aubFontName); pxlpdev->pXLFont->SetFont(pGState->GetFontType(), aubFontName, pGState->GetFontHeight(), pGState->GetFontWidth(), pGState->GetFontSymbolSet(), pGState->GetFontSimulation());
pGState->ResetFont();
return TRUE; }
|