#ifndef _FACEREALIZATION_ #define _FACEREALIZATION_ #define GLYPHDATABLOCKCOUNT 16 #define MAXRECENTLYUSEDCOUNT 32 #define EMPTY_GLYPH_FFFF 0xFFFF // Display nothing, neither ink nor width. // Typedefs for cached funtion pointers in GpFaceRealization. class GpFaceRealization; /* used in aatext.cxx and facerealization.cpp : */ #define CJ_CTGD(cx,cy) (ALIGN4(offsetof(GLYPHBITS,aj)) + ALIGN4((cx) * (cy))) #define ALIGN4(X) (((X) + 3) & ~3) #define ALIGN(object, p) p = (p + ((UINT)sizeof(object) - 1)) & ~((UINT)sizeof(object) - 1); inline BOOL IsGridFittedTextRealizationMethod(TextRenderingHint method) { switch (method) { case TextRenderingHintSingleBitPerPixelGridFit: case TextRenderingHintAntiAliasGridFit: case TextRenderingHintClearTypeGridFit: return TRUE; default: return FALSE; } } ///// GpGlyphMetrics // // Metrics for text handling and glyph placement. // There are separate records for horizontal and vertical baselines. struct GpGlyphMetrics { // Metrics along baseline in 28.4 INT AdvanceWidth; INT LeadingSidebearing; INT TrailingSidebearing; PointF Origin; // Float }; struct GpGlyphAABits { GpGlyphAABits * Next; ULONG X, Y; BYTE Bits[1]; // variable size }; struct GpGlyphData { GpGlyphMetrics GlyphMetrics[2]; // one for horizontal metrics and one for vertical metrics union { GLYPHBITS *GlyphBits; // Same as GDI structure at this moment GpGlyphPath *GlyphPath; GpGlyphAABits *GlyphAABits; // null terminated singly-linked list }; }; struct GlyphDataBlock { GlyphDataBlock *NextGlyphDataBlock; GpGlyphData GlyphDataArray[GLYPHDATABLOCKCOUNT]; }; // blocks of memory used to store glyphbits struct GlyphBitsBlock { GlyphBitsBlock *NextGlyphBitsBlock; // next block in the list UINT SizeGlyphBitsBlock; // Bytes allocated BYTE Bits[1]; // bits }; //// CacheFaceRealization - cache entries referenced by FaceRealization // // class EXTFONTOBJ { public: FONTOBJ fobj; // pass to DDI, we need to have it to back compatible with GDI }; enum GpGlyphDataCacheType { CacheBits, CachePath, CacheAABits }; class CacheFaceRealization : public EXTFONTOBJ { public: // New type information BOOL NoCache; // Cache type - GpGlyphDataCacheType CacheType; // bits, path or AA bits BOOL ForcedPath; // was this CacheFaceRealization forced to use path because of huge font size // claudebe, try to get rid of both, redundant with fontObj flags : should correspond to what is actually realized TextRenderingHint realizationMethod; ULONG QueryFontDataMode; // Physical font information (font source). const GpFontFace *Face; // pointer to physical font entry // Font transform information. // DDI callback transform object. A reference to this EXFORMOBJ is passed // to the driver so that it can callback XFORMOBJ_ services for the notional // to device transform for this font. GpMatrix mxForDDI; // xoForDDI's matrix // cached here upon font realization for fast access ULONG MaxGlyphByteCount; // (MaxGlyphPixelWidth + 7)/8 * MaxGlyphPixelHeight, or at least it should be for 1 bpp FD_DEVICEMETRICS DeviceMetrics; // Hinted metric indformation // Root of per glyph metrics and images GpGlyphData **GlyphDataArray; // array of pointers to GpGlyphData's // CacheFaceRealization linked list for a particular face CacheFaceRealization *NextCacheFaceRealization; CacheFaceRealization *PreviousCacheFaceRealization; // CacheFaceRealization last recently used linked list CacheFaceRealization *NextRecentCacheFaceRealization; CacheFaceRealization *PreviousRecentCacheFaceRealization; // Font cache information. GlyphDataBlock *FirstGlyphDataBlock; // First block in chain - used for destruction GlyphBitsBlock *FirstGlyphBitsBlock; // Info for GlyphDataBlock being constructed GlyphDataBlock *GlyphDataBlockUnderConstruction; UINT NextFreeGlyphDataIndex; // (All other blocks are already full) // Info for GlyphBitBlock under construction GlyphBitsBlock *GlyphBitsBlockUnderConstruction; UINT SizeGlyphBitsBlockUnderConstruction; // Bytes allocated UINT UsedBytesGlyphBitsBlockUnderConstruction; // Bytes used // Lookaside cache - holds bits or path and metrics for a single glyph, used whern // data too big for cache block. GpGlyphData *LookasideGlyphData; // Same as GDI structure at this moment SIZE_T LookasideByteCount; // size of current lookaside buffer // claudebe : still need to be updated to use the global cache size limit : UINT cBlocksMax; // max # of blocks allowed UINT cBlocks; // # of blocks allocated so far }; //// FaceRealization // // Represents a font at a given size (?on a given device?) class GpFaceRealization { private: mutable CacheFaceRealization *prface; GpStatus Status; INT Style; BOOL LimitSubpixel; public: // Constructors -- Lock the CacheFaceRealization. GpFaceRealization() : prface (NULL), Status (InvalidParameter) {} GpFaceRealization( const GpFontFace *pface, INT style, const GpMatrix *matrix, const SizeF dpi, TextRenderingHint renderMethod, BOOL bPath, BOOL bCompatibleWidth, /* we want ClearType compatible width when we come from DrawDriverString */ BOOL bSideways /* for far east vertical writing, run of glyph layed out sideways, used to do the italic simulation in the right direction */ ); // Destructor -- Unlocks the CacheFaceRealization ~GpFaceRealization(); // To clone another GpFaceRealiztion from Bits to Path void CloneFaceRealization( const GpFaceRealization * pfaceRealizaton, BOOL bPath ); // GetStatus - Called following instantiation to check that construction worked. GpStatus GetStatus() const {return Status;} INT GetStyle() const { #if DBG INT style = 0; if ( prface->Face->pifi->fsSelection & FM_SEL_BOLD || prface->fobj.flFontType & FO_SIM_BOLD) { style |= FontStyleBold; } if ( prface->Face->pifi->fsSelection & FM_SEL_ITALIC || prface->fobj.flFontType & FO_SIM_ITALIC_SIDEWAYS || prface->fobj.flFontType & FO_SIM_ITALIC) { style |= FontStyleItalic; } ASSERT(style == (Style & (FontStyleBold | FontStyleItalic))); #endif return Style; } BOOL bInit( const GpFontFace *pface, INT style, const GpMatrix *matrix, SizeF dpi, TextRenderingHint textMode, BOOL bPath, BOOL bCompatibleWidth, /* we want ClearType compatible width when we come from DrawDriverString */ BOOL bSideways /* for far east vertical writing, run of glyph layed out sideways, used to do the italic simulation in the right direction */ ); // bDelete -- Removes an CacheFaceRealization BOOL DeleteRealizedFace(); // Reuse an CacheFaceRealization BOOL ReuseRealizedFace(); // bInitCache -- Initialize the cache BOOL bInitCache() const; BOOL AllocateCache() const; // vDeleteCache -- Delete the CACHE from existence. VOID vDeleteCache() const; BOOL noCache() const {return prface->NoCache ;} // FindRealizedFace -- check to see whether there is existing realization // on the CacheFaceRealization list in the GpFontFile. BOOL FindRealizedFace( FD_XFORM *fdx, const GpFontFace *fontFace, BOOL needPaths, FLONG fl ) const; // RealizeFont -- Initializer; for IFI, calls driver to realize // font represented by PFE. BOOL Realize( SizeF dpi, const GpFontFace *pfe, INT style, // style - which may require simulation PFD_XFORM pfdx, // font xform (Notional to Device) FLONG fl, // these two really modify the xform BOOL bNeedPaths ); // Valid -- Returns TRUE if object was successfully locked BOOL IsValid () { return(prface != 0); } ULONG QueryFontDataMode() const { return prface->QueryFontDataMode; } BOOL bGetDEVICEMETRICS(); // return the font face for this RFace const GpFontFace * GetFontFace() const {return(prface->Face);} // Is it in private font file table or not BOOL IsPrivate() const {return prface->Face->IsPrivate();} // pfdx -- Return pointer to the notional to device font transform. FD_XFORM *pfdx() const {return (&prface->fobj.fdx);} // pfo -- Return pointer to the font object FONTOBJ *pfo() const {return(&prface->fobj);} // kill driver realization of the font, i.e. "FONT CONTEXT" in the old lingo. // Method calling DrvDestroyFont before CacheFaceRealization is killed itself. VOID vDestroyRealizedFace(); // vGetCache -- Claims the cache semaphore VOID vGetCache () { // EnterCriticalSection(&prface->FaceRealizationCritSection); } // vReleaseCache -- Releases the cache semaphore VOID vReleaseCache () { if ( prface->LookasideGlyphData != NULL ) { GpFree((PVOID) prface->LookasideGlyphData); prface->LookasideByteCount = 0; prface->LookasideGlyphData = NULL; } // LeaveCriticalSection(&prface->FaceRealizationCritSection); } ULONG GetGlyphsSupported() const { if (prface && prface->Face) { return (prface->Face->NumGlyphs); } return 0; } GpStatus GetGlyphStringDeviceAdvanceVector( const UINT16 *glyphs, INT glyphCount, BOOL vertical, REAL *deviceAdvances ) const; GpStatus GetGlyphStringDeviceAdvanceVector( const UINT16 *glyphs, INT glyphCount, BOOL vertical, INT *deviceAdvances // Returned in 28.4 ) const; GpStatus GetGlyphStringIdealAdvanceVector( const UINT16 *glyphs, INT glyphCount, REAL deviceToIdeal, BOOL vertical, INT *idealAdvances ) const; GpStatus GetGlyphStringSidebearings( const UINT16 *glyphs, INT glyphCount, BOOL vertical, BOOL reverse, // For example right-to-left INT *leadingSidebearing, // 28.4 INT *trailingSidebearing // 28.4 ) const; GpStatus GetGlyphStringVerticalOriginOffsets( IN const UINT16 *glyphs, IN INT glyphCount, OUT PointF *offsets ) const; // GetGlyphPath GpStatus GetGlyphPath( const UINT16 glyphIndice, GpGlyphPath **pGlyphPath, PointF *sidewaysOffset ) const; // GetGlyphPos INT GetGlyphPos( const INT cGlyphs, // How many glyphs Client want to request const UINT16 *glyphIndex, // An array of glyph index GpGlyphPos *pgpos, // An array of GLYPHPOS const PointF *glyphOrigin, // X,Y positions for sub-pixel calculation INT *cParsed, // How many glyphs we parsed BOOL sideways // e.g. FE characters in vertical text ) const; // Realization mode inline TextRenderingHint RealizationMethod() const {return(prface->realizationMethod);} // IisPathFont -- Is this a path font? inline BOOL IsPathFont() const {return(prface->CacheType == CachePath);} VOID FlushCache() const; // Construction hack used by GpFaceRealizationTMP during CacheFaceRealization cleanup void Setprface(CacheFaceRealization *rface) {prface = rface;} CacheFaceRealization *Getprface() const {return prface;} INT GetXMin() const {return prface->DeviceMetrics.xMin;}; INT GetXMax() const {return prface->DeviceMetrics.xMax;}; INT GetYMin() const {return prface->DeviceMetrics.yMin;}; INT GetYMax() const {return prface->DeviceMetrics.yMax;}; BOOL IsHorizontalTransform() const {return prface->DeviceMetrics.HorizontalTransform;}; BOOL IsVerticalTransform() const {return prface->DeviceMetrics.VerticalTransform;}; BOOL IsFixedPitch() const {return (prface->Face->pifi->flInfo & FM_INFO_OPTICALLY_FIXED_PITCH);}; BOOL GetLimitSubpixel() { return LimitSubpixel; } void SetLimitSubpixel(BOOL limitSubpixel) { LimitSubpixel = limitSubpixel; } private: GpStatus CheckGlyphStringMetricsCached(const UINT16 *glyphs, INT glyphCount) const; // vInsert -- Insert this CacheFaceRealization onto the head of an CacheFaceRealization doubly linked list. VOID vInsert (CacheFaceRealization **pprfaceHead); // vRemove -- Remove this CacheFaceRealization from an CacheFaceRealization doubly linked list. VOID vRemove (CacheFaceRealization **pprfaceHead); // Access to cached glyph data GpGlyphData *GetGlyphDataCached(UINT16 glyphIndex, BOOL allowFlush) const; GpGlyphData *GetGlyphDataLookaside(UINT16 glyphIndex) const; BOOL CheckMetricsCache() const; VOID *pgbCheckGlyphCache(SIZE_T cjNeeded) const; VOID ConvertGLYPHDATAToGpGlyphMetrics( IN INT glyphIndex, IN GLYPHDATA *pgd, OUT GpGlyphData *pgpgd ) const; GpStatus IsMetricsCached(UINT16 glyph, ULONG * pcjNeeded) const; BOOL InsertGlyphBits(UINT16 glyph, ULONG cjNeeded, BOOL bFlushOk) const; BOOL InsertGlyphPath(UINT16 glyph, BOOL allowFlush) const; // bMatchFDXForm -- Is pfdx identical to current font xform? inline BOOL MatchFDXForm(FD_XFORM *pfdx) const { return(!memcmp((PBYTE)pfdx, (PBYTE)&prface->fobj.fdx, sizeof(FD_XFORM))); } // Calculating sub-pixel position BOOL GetAAGlyphDataCached( UINT16 glyphIndex, GpGlyphPos * pgpos, BOOL allowFlush, INT x, INT y, BOOL sideways // e.g. FE characters in vertical text ) const; }; class GpFaceRealizationTMP : public GpFaceRealization { public: GpFaceRealizationTMP(CacheFaceRealization *_prface) {Setprface(_prface);} ~GpFaceRealizationTMP() {Setprface(NULL);} }; class GpCacheFaceRealizationList { public: GpCacheFaceRealizationList() { head = NULL; count = 0; } ~GpCacheFaceRealizationList(); void AddMostRecent(CacheFaceRealization *prface); void RemoveFace(CacheFaceRealization *prface); CacheFaceRealization *ReuseLeastRecent (void); INT GetCount() {return count; } private: CacheFaceRealization *head; INT count; }; #endif // __FACEREALIZATION__