Annotation of ntddk/src/video/displays/jz484/text.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1991-1992  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:    Text.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This module attempts to cache fonts on the VXL video board and draw glyphs
        !            12:     using hardware acceleration,
        !            13:     If the font cannot be cached the Engine is called to draw the glyphs.
        !            14: 
        !            15: Environment:
        !            16: 
        !            17: 
        !            18: Revision History:
        !            19: 
        !            20: --*/
        !            21: 
        !            22: #include "driver.h"
        !            23: #include "jzvxl484.h"
        !            24: 
        !            25: //
        !            26: // The following macro is the hash function for computing the cache
        !            27: // index from a Glyph Handle and  FontId.
        !            28: //
        !            29: 
        !            30: #define HASH_FUNCTION(GlyphHandle,FontId) \
        !            31:     ((GlyphHandle & 0x7FF) << 1) + \
        !            32:     FontId + \
        !            33:     (FontId << 7)
        !            34: 
        !            35: 
        !            36: 
        !            37: //#define CACHE_STATS
        !            38: 
        !            39: //
        !            40: // Define string object accelerator masks.
        !            41: //
        !            42: 
        !            43: #define SO_MASK \
        !            44:     (SO_FLAG_DEFAULT_PLACEMENT | SO_ZERO_BEARINGS | \
        !            45:      SO_CHAR_INC_EQUAL_BM_BASE | SO_MAXEXT_EQUAL_BM_SIDE)
        !            46: 
        !            47: #define SO_LTOR (SO_MASK | SO_HORIZONTAL)
        !            48: #define SO_RTOL (SO_LTOR | SO_REVERSED)
        !            49: #define SO_TTOB (SO_MASK | SO_VERTICAL)
        !            50: #define SO_BTOT (SO_TTOB | SO_REVERSED)
        !            51: 
        !            52: static ULONG TextForegroundColor = 0xFFFFFFFF;
        !            53: static ULONG TextBackgroundColor = 0xFFFFFFFF;
        !            54: 
        !            55: #ifdef CACHE_STATS
        !            56: static ULONG CacheUnused = Vxl.CacheSize;
        !            57: static ULONG CharCount = 0;
        !            58: static ULONG CacheMisses = 0;
        !            59: static ULONG CacheReplacement = 0;
        !            60: static ULONG ReplacementTotal = 0;
        !            61: static ULONG CharTotal = 0;
        !            62: static ULONG MissTotal = 0;
        !            63: static ULONG HigherFontId = 0;
        !            64: static ULONG HigherGlyphHandle = 0;
        !            65: #endif
        !            66: 
        !            67: static UCHAR ToBigEndian[256] = {
        !            68:     0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
        !            69:     0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
        !            70:     0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
        !            71:     0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
        !            72:     0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
        !            73:     0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
        !            74:     0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
        !            75:     0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
        !            76:     0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
        !            77:     0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
        !            78:     0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
        !            79:     0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
        !            80:     0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
        !            81:     0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
        !            82:     0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
        !            83:     0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
        !            84:     };
        !            85: 
        !            86: 
        !            87: 
        !            88: BOOL
        !            89: DrvTextOut
        !            90: (
        !            91:     IN SURFOBJ  *pso,
        !            92:     IN STROBJ   *pstro,
        !            93:     IN FONTOBJ  *pfo,
        !            94:     IN CLIPOBJ  *pco,
        !            95:     IN RECTL    *prclExtra,
        !            96:     IN RECTL    *prclOpaque,
        !            97:     IN BRUSHOBJ *pboFore,
        !            98:     IN BRUSHOBJ *pboOpaque,
        !            99:     IN POINTL   *pptlOrg,
        !           100:     IN MIX       mix
        !           101: )
        !           102: /*++
        !           103: 
        !           104: Routine Description:
        !           105: 
        !           106:     This function will cache fonts on the VXL video board and use accelerator
        !           107:     hardware to draw each glyph. An attemp is made to use opaque mode
        !           108:     text output to draw text and background color at the same time. If this
        !           109:     cannot be done then glyph forground and backgrounds are drawn spearately.
        !           110: 
        !           111: Arguments:
        !           112: 
        !           113:     MIX is not checked. Since the GCAPS_ARBMIXTEXT capability bit is not
        !           114:     set, mix mode is always R2_COPYPEN.
        !           115: 
        !           116: Return Value:
        !           117: 
        !           118: 
        !           119: --*/
        !           120: 
        !           121: {
        !           122:     BOOL         bMoreGlyphs;
        !           123:     LONG         LineIndex;
        !           124:     ULONG        ByteIndex;
        !           125:     PGLYPHPOS    GlyphPosList;
        !           126:     ULONG        GlyphCount;
        !           127:     ULONG        GlyphHandle;
        !           128:     ULONG        CacheIndex;
        !           129:     ULONG        FontId;
        !           130:     GLYPHBITS    *FontBitMap;
        !           131:     PBYTE        BitMapPtr;
        !           132:     ULONG        X,Y;
        !           133:     BOOL         Allocate;
        !           134:     PULONG       CacheData;
        !           135:     ULONG        BitMapData;
        !           136:     ULONG        SrcAdr,DstAdr,XYCmd,Cmd;
        !           137:     PGLYPHPOS    GlyphEnd;
        !           138:     PGLYPHPOS    GlyphStart;
        !           139:     LONG         GlyphStride;
        !           140:     RECTL        OpaqueRectl;
        !           141:     ULONG        GlyphBytesPerScan,ShiftAmount;
        !           142: 
        !           143:     //
        !           144:     //  Make sure the surface is the screen.
        !           145:     //
        !           146: 
        !           147:     if (pso->pvBits != (PVOID)Vxl.ScreenBase) {
        !           148:         goto DevFailTextOut;
        !           149:     }
        !           150: 
        !           151:     //
        !           152:     // If the width of the glyph is bigger than what the accelerator supports
        !           153:     //    The font is non cacheable
        !           154:     //    Clipping is not trivial OR
        !           155:     //    SolidColor is a brush.
        !           156:     // call GDI to draw the text.
        !           157:     //
        !           158: 
        !           159: 
        !           160:     if ((pfo->cxMax > 32) ||
        !           161:         (pfo->flFontType & DEVICE_FONTTYPE) ||
        !           162:         (pco->iDComplexity != DC_TRIVIAL) ||
        !           163:         (pboFore->iSolidColor == 0xFFFFFFFFL)) {
        !           164: 
        !           165:         goto DevFailTextOut;
        !           166:     }
        !           167: 
        !           168:     //
        !           169:     // Set Jaguar foreground color only if it changed since the
        !           170:     // previous call. Changing Foreground/Background color requires
        !           171:     // synchronization.
        !           172:     //
        !           173: 
        !           174:     if (TextForegroundColor != pboFore->iSolidColor) {
        !           175:         TextForegroundColor =  pboFore->iSolidColor;
        !           176:         DevSetFgColor(TextForegroundColor);
        !           177:     }
        !           178: 
        !           179:     //
        !           180:     // Check that the Background color is solid.
        !           181:     // Set Jaguar Background color if it changed.
        !           182:     //
        !           183: 
        !           184:     if (prclOpaque != (PRECTL) NULL) {
        !           185:         if (pboOpaque->iSolidColor == 0xFFFFFFFFL) {
        !           186:             goto DevFailTextOut;
        !           187:         }
        !           188:         if (TextBackgroundColor != pboOpaque->iSolidColor) {
        !           189:             TextBackgroundColor = pboOpaque->iSolidColor;
        !           190:             DevSetBgColor(TextBackgroundColor);
        !           191:         }
        !           192:     }
        !           193: 
        !           194:     //
        !           195:     //  enumerate the string psto into glyphs (GLYPHPOS), then send a draw
        !           196:     //  command for each. Deal with clipping later.
        !           197:     //
        !           198: 
        !           199:     FontId = pfo->iUniq;
        !           200: #ifdef CACHE_STATS
        !           201:     if (FontId > HigherFontId) {
        !           202:         HigherFontId = FontId;
        !           203:     }
        !           204: #endif
        !           205:     if (((pstro->flAccel == SO_LTOR) || (pstro->flAccel == SO_RTOL) ||
        !           206:         (pstro->flAccel == SO_TTOB) || (pstro->flAccel == SO_BTOT)) &&
        !           207:         (prclOpaque != NULL)) {
        !           208: 
        !           209:         //
        !           210:         // If the top of the opaque rectangle is less than the top of the
        !           211:         // background rectangle, then fill the region between the top of
        !           212:         // opaque rectangle and the top of the background rectangle and
        !           213:         // reduce the size of the opaque rectangle.
        !           214:         //
        !           215: 
        !           216:         OpaqueRectl = *prclOpaque;
        !           217:         if (OpaqueRectl.top < pstro->rclBkGround.top) {
        !           218:             OpaqueRectl.bottom = pstro->rclBkGround.top;
        !           219:             DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor);
        !           220:             OpaqueRectl.top = pstro->rclBkGround.top;
        !           221:             OpaqueRectl.bottom = prclOpaque->bottom;
        !           222:         }
        !           223: 
        !           224:         //
        !           225:         // If the bottom of the opaque rectangle is greater than the bottom
        !           226:         // of the background rectangle, then fill the region between the
        !           227:         // bottom of the background rectangle and the bottom of the opaque
        !           228:         // rectangle and reduce the size of the opaque rectangle.
        !           229:         //
        !           230: 
        !           231:         if (OpaqueRectl.bottom > pstro->rclBkGround.bottom) {
        !           232:             OpaqueRectl.top = pstro->rclBkGround.bottom;
        !           233:             DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor);
        !           234:             OpaqueRectl.top = pstro->rclBkGround.top;
        !           235:             OpaqueRectl.bottom = pstro->rclBkGround.bottom;
        !           236:         }
        !           237: 
        !           238:         //
        !           239:         // If the left of the opaque rectangle is less than the left of
        !           240:         // the background rectangle, then fill the region between the
        !           241:         // left of the opaque rectangle and the left of the background
        !           242:         // rectangle.
        !           243:         //
        !           244: 
        !           245:         if (OpaqueRectl.left < pstro->rclBkGround.left) {
        !           246:             OpaqueRectl.right = pstro->rclBkGround.left;
        !           247:             DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor);
        !           248:             OpaqueRectl.right = prclOpaque->right;
        !           249:         }
        !           250: 
        !           251:         //
        !           252:         // If the right of the opaque rectangle is greater than the right
        !           253:         // of the background rectangle, then fill the region between the
        !           254:         // right of the opaque rectangle and the right of the background
        !           255:         // rectangle.
        !           256:         //
        !           257: 
        !           258:         if (OpaqueRectl.right > pstro->rclBkGround.right) {
        !           259:             OpaqueRectl.left = pstro->rclBkGround.right;
        !           260:             DrvpFillRectangle(&OpaqueRectl, pboOpaque->iSolidColor);
        !           261:         }
        !           262: 
        !           263:         Cmd = JAGUAR_TEXT_OPAQUE << XYCMD_CMD_SHIFT;
        !           264: 
        !           265:     } else {
        !           266: 
        !           267:         //
        !           268:         //  We now have a cacheable font and drawable rectangles, first clip and draw
        !           269:         //  all opaque rectangles.
        !           270:         //
        !           271: 
        !           272:         if (prclOpaque != (PRECTL)NULL) {
        !           273: 
        !           274:             DrvpFillRectangle(prclOpaque,pboOpaque->iSolidColor);
        !           275: 
        !           276:         }
        !           277:         Cmd = JAGUAR_TEXT_TRANSPARENT << XYCMD_CMD_SHIFT;
        !           278:     }
        !           279: 
        !           280:     //
        !           281:     // If the font is fixed pitch, then optimize the computation of
        !           282:     // x and y coordinate values. Otherwise, compute the x and y values
        !           283:     // for each glyph.
        !           284:     //
        !           285: 
        !           286:     if (pstro->ulCharInc != 0) {
        !           287: 
        !           288:         //
        !           289:         // The font is fixed pitch. Capture the glyph dimensions and
        !           290:         // compute the starting display address.
        !           291:         //
        !           292: 
        !           293:         if (pstro->pgp == NULL) {
        !           294:             bMoreGlyphs = STROBJ_bEnum(pstro, &GlyphCount, &GlyphPosList);
        !           295: 
        !           296:         } else {
        !           297:             GlyphCount = pstro->cGlyphs;
        !           298:             GlyphPosList = pstro->pgp;
        !           299:             bMoreGlyphs = FALSE;
        !           300:         }
        !           301: 
        !           302: #ifdef CACHE_STATS
        !           303:     CharCount += GlyphCount;
        !           304: #endif
        !           305: 
        !           306:         FontBitMap = GlyphPosList->pgdf->pgb;
        !           307:         X = FontBitMap->sizlBitmap.cx;
        !           308:         Y = FontBitMap->sizlBitmap.cy;
        !           309: 
        !           310:         DstAdr = ((GlyphPosList->ptl.y + FontBitMap->ptlOrigin.y) * Vxl.JaguarScreenX) +
        !           311:                  ((GlyphPosList->ptl.x + FontBitMap->ptlOrigin.x) << Vxl.ColorModeShift) ;
        !           312: 
        !           313:         //
        !           314:         // Compute the glyph stride.
        !           315:         //
        !           316: 
        !           317:         GlyphStride = ((pstro->ulCharInc) << Vxl.ColorModeShift);
        !           318:         if ((pstro->flAccel & SO_VERTICAL) != 0) {
        !           319:             GlyphStride *= Vxl.JaguarScreenX;
        !           320:         }
        !           321: 
        !           322:         //
        !           323:         // If the direction of drawing is reversed, then the stride is
        !           324:         // negative.
        !           325:         //
        !           326: 
        !           327:         if ((pstro->flAccel & SO_REVERSED) != 0) {
        !           328:             GlyphStride = -GlyphStride;
        !           329:         }
        !           330: 
        !           331:         //
        !           332:         // Output the set of glyphs.
        !           333:         //
        !           334: 
        !           335:         do {
        !           336:             GlyphEnd = &GlyphPosList[GlyphCount];
        !           337:             GlyphStart = GlyphPosList;
        !           338:             do {
        !           339: 
        !           340:                 GlyphHandle = (ULONG) (GlyphStart->hg);
        !           341: 
        !           342:                 CacheIndex = HASH_FUNCTION(GlyphHandle,FontId);
        !           343: 
        !           344:                 CacheIndex &= Vxl.CacheIndexMask;
        !           345: 
        !           346:                 //
        !           347:                 // Get glyph info
        !           348:                 //
        !           349: 
        !           350:                 FontBitMap = GlyphStart->pgdf->pgb;
        !           351: 
        !           352:                 //
        !           353:                 // If FontId or GlyphHandle don't match, cache this glyph.
        !           354:                 //
        !           355: 
        !           356:                 if (Vxl.CacheTag[CacheIndex].FontId != FontId) {
        !           357:                     Allocate = TRUE;
        !           358:                 } else {
        !           359:                     if (Vxl.CacheTag[CacheIndex].GlyphHandle != GlyphHandle) {
        !           360:                         Allocate = TRUE;
        !           361:                     } else {
        !           362:                         Allocate = FALSE;
        !           363:                     }
        !           364:                 }
        !           365:                 if (Allocate) {
        !           366: 
        !           367:                     //
        !           368:                     // Wait for the accelerator to be idle to ensure
        !           369:                     // that the glyph being replaced is not in use.
        !           370:                     //
        !           371: 
        !           372:                     WaitForJaguarIdle();
        !           373: 
        !           374: #ifdef CACHE_STATS
        !           375:                     CacheMisses++;
        !           376: 
        !           377:                     if (Vxl.CacheTag[CacheIndex].FontId == FreeTag) {
        !           378:                         CacheUnused--;
        !           379:                     } else {
        !           380:                         CacheReplacement++;
        !           381:                     }
        !           382: 
        !           383:                     if (Vxl.CacheTag[CacheIndex].FontId == FontId) {
        !           384:                         DISPDBG((3, "Replacing same font Glyph %x with glyph %x\n",
        !           385:                         Vxl.CacheTag[CacheIndex].FontId,
        !           386:                         FontId));
        !           387:                     }
        !           388: 
        !           389:                     if (Vxl.CacheTag[CacheIndex].GlyphHandle == GlyphHandle) {
        !           390:                         DISPDBG((3, "Replacing same Glyph %x font %x with font %x\n",
        !           391:                         GlyphHandle,
        !           392:                         Vxl.CacheTag[CacheIndex].FontId,
        !           393:                         FontId));
        !           394:                     }
        !           395: 
        !           396:                     if (GlyphHandle > HigherGlyphHandle) {
        !           397:                         HigherGlyphHandle = GlyphHandle;
        !           398:                     }
        !           399: #endif
        !           400:                     //
        !           401:                     // if the entry that needs to be replaced
        !           402:                     // is used as extension for a glyph > 32 lines
        !           403:                     // go backwards and clear the Id so that if the
        !           404:                     // glyph > 32 is used again it'll miss in the cache
        !           405:                     //
        !           406:                     //
        !           407: 
        !           408:                     LineIndex = CacheIndex;
        !           409:                     while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) {
        !           410:                         LineIndex--;
        !           411:                         Vxl.CacheTag[LineIndex].FontId = FreeTag;
        !           412:                     }
        !           413: 
        !           414:                     //
        !           415:                     // Clear the entries used by the big glyph that follows the one
        !           416:                     // that needs to be replaced
        !           417:                     //
        !           418: 
        !           419:                     LineIndex = CacheIndex+1;
        !           420:                     while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) {
        !           421:                         Vxl.CacheTag[LineIndex].FontId = FreeTag;
        !           422:                         LineIndex++;
        !           423:                     }
        !           424: 
        !           425:                     //
        !           426:                     //  Store the tag for the current glyph.
        !           427:                     //
        !           428: 
        !           429:                     Vxl.CacheTag[CacheIndex].FontId = FontId;
        !           430:                     Vxl.CacheTag[CacheIndex].GlyphHandle = GlyphHandle;
        !           431: 
        !           432:                     CacheData = Vxl.FontCacheBase + (CacheIndex << 5);
        !           433: 
        !           434:                     //
        !           435:                     // Fix the bit ordering and store the bitmap
        !           436:                     // in off screen video memory.
        !           437:                     //
        !           438: 
        !           439:                     BitMapPtr = FontBitMap->aj;
        !           440:                     GlyphBytesPerScan = (X+7) >> 3;
        !           441:                     ShiftAmount  = (GlyphBytesPerScan-1) << 3;
        !           442: 
        !           443: 
        !           444:                     for (LineIndex=0;LineIndex < Y; LineIndex ++) {
        !           445:                         BitMapData = 0;
        !           446: 
        !           447: 
        !           448:                         for (ByteIndex = 0; ByteIndex < GlyphBytesPerScan; ByteIndex++) {
        !           449:                             BitMapData >>= 8;
        !           450:                             BitMapData |= ToBigEndian[*BitMapPtr++] << ShiftAmount;
        !           451:                         }
        !           452:                         *CacheData++ = BitMapData;
        !           453:                     }
        !           454: 
        !           455:                     //
        !           456:                     // If Y is bigger than 32 lines, the glyph that was just cached
        !           457:                     // took more than one entry. Fix the CacheTags.
        !           458:                     //
        !           459: 
        !           460:                     for (ByteIndex = 1; LineIndex > 32 ;ByteIndex++) {
        !           461:                         Vxl.CacheTag[CacheIndex+ByteIndex].FontId = GlyphExtended;
        !           462:                         LineIndex -=32;
        !           463:                     }
        !           464:                 }
        !           465: 
        !           466:                 //
        !           467:                 // Find out where to draw the glyph and the glyph's starting address
        !           468:                 //
        !           469: 
        !           470:                 SrcAdr = Vxl.FontCacheOffset + (CacheIndex << 7);
        !           471: 
        !           472:                 XYCmd = Cmd | (Y << XYCMD_Y_SHIFT) | X;
        !           473: 
        !           474:                 FifoWrite(DstAdr,SrcAdr,XYCmd);
        !           475: 
        !           476:                 DstAdr += GlyphStride;
        !           477:                 GlyphStart += 1;
        !           478:             } while (GlyphStart != GlyphEnd);
        !           479: 
        !           480:             if (bMoreGlyphs) {
        !           481:                 bMoreGlyphs = STROBJ_bEnum(pstro, &GlyphCount, &GlyphPosList);
        !           482: #ifdef CACHE_STATS
        !           483:                 CharCount += GlyphCount;
        !           484: #endif
        !           485: 
        !           486:             } else {
        !           487:                 break;
        !           488:             }
        !           489:         } while (TRUE);
        !           490: 
        !           491:     } else {
        !           492: 
        !           493:         //
        !           494:         // The font is not fixed pitch. Compute the x and y values for
        !           495:         // each glyph individually.
        !           496:         //
        !           497: 
        !           498:         do {
        !           499: 
        !           500:             //
        !           501:             //  Get each glyph handle, find the physical address and send the
        !           502:             //  draw command to the accelerator. Don't worry about clipping yet.
        !           503:             //
        !           504: 
        !           505:             bMoreGlyphs = STROBJ_bEnum(pstro, &GlyphCount,&GlyphPosList);
        !           506: 
        !           507: #ifdef CACHE_STATS
        !           508:             CharCount += GlyphCount;
        !           509: #endif
        !           510: 
        !           511:             GlyphEnd = &GlyphPosList[GlyphCount];
        !           512:             GlyphStart = GlyphPosList;
        !           513:             do {
        !           514: 
        !           515:                 GlyphHandle = (ULONG) (GlyphStart->hg);
        !           516: 
        !           517:                 CacheIndex = HASH_FUNCTION(GlyphHandle,FontId);
        !           518: 
        !           519:                 CacheIndex &= Vxl.CacheIndexMask;
        !           520: 
        !           521:                 //
        !           522:                 // Get glyph info
        !           523:                 //
        !           524: 
        !           525:                 FontBitMap = GlyphStart->pgdf->pgb;
        !           526:                 X = FontBitMap->sizlBitmap.cx;
        !           527:                 Y = FontBitMap->sizlBitmap.cy;
        !           528: 
        !           529:                 //
        !           530:                 // If FontId or GlyphHandle don't match, cache this glyph.
        !           531:                 //
        !           532: 
        !           533: 
        !           534:                 if (Vxl.CacheTag[CacheIndex].FontId != FontId) {
        !           535:                     Allocate = TRUE;
        !           536:                 } else {
        !           537:                     if (Vxl.CacheTag[CacheIndex].GlyphHandle != GlyphHandle) {
        !           538:                         Allocate = TRUE;
        !           539:                     } else {
        !           540:                         Allocate = FALSE;
        !           541:                     }
        !           542:                 }
        !           543: 
        !           544:                 if (Allocate) {
        !           545: 
        !           546:                     //
        !           547:                     // Wait for the accelerator to be idle to ensure
        !           548:                     // that the glyph being replaced is not in use.
        !           549:                     //
        !           550:                     WaitForJaguarIdle();
        !           551: 
        !           552: #ifdef CACHE_STATS
        !           553:                     CacheMisses++;
        !           554: #endif
        !           555: 
        !           556:                     //
        !           557:                     // The Glyph that has to be replaced is from the same font,
        !           558:                     // wait for the accelerator to be idle before caching the
        !           559:                     // glyph.
        !           560:                     //
        !           561: 
        !           562: #ifdef CACHE_STATS
        !           563:                     if (Vxl.CacheTag[CacheIndex].FontId == FreeTag) {
        !           564:                         CacheUnused--;
        !           565:                     } else {
        !           566:                         CacheReplacement++;
        !           567:                     }
        !           568: 
        !           569:                     if (Vxl.CacheTag[CacheIndex].FontId == FontId) {
        !           570:                         DISPDBG((3, "Replacing same font Glyph %x with glyph %x\n",
        !           571:                         Vxl.CacheTag[CacheIndex].FontId,
        !           572:                         FontId));
        !           573:                     }
        !           574: 
        !           575:                     if (Vxl.CacheTag[CacheIndex].GlyphHandle == GlyphHandle) {
        !           576:                         DISPDBG((3, "Replacing same Glyph %x font %x with font %x\n",
        !           577:                             GlyphHandle,
        !           578:                             Vxl.CacheTag[CacheIndex].FontId,
        !           579:                             FontId));
        !           580:                     }
        !           581: 
        !           582:                     if (GlyphHandle > HigherGlyphHandle) {
        !           583:                         HigherGlyphHandle = GlyphHandle;
        !           584:                     }
        !           585: #endif
        !           586: 
        !           587:                     //
        !           588:                     // if the entry that needs to be replaced
        !           589:                     // is used as extension for a glyph > 32 lines
        !           590:                     // go backwards and clear the Id so that if the
        !           591:                     // glyph > 32 is used again it'll miss in the cache
        !           592:                     //
        !           593: 
        !           594:                     LineIndex = CacheIndex;
        !           595:                     while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) {
        !           596:                         LineIndex--;
        !           597:                         Vxl.CacheTag[LineIndex].FontId = FreeTag;
        !           598:                     }
        !           599: 
        !           600:                     //
        !           601:                     // Clear the entries used by the big glyph that follows the one
        !           602:                     // that needs to be replaced
        !           603:                     //
        !           604: 
        !           605:                     LineIndex = CacheIndex+1;
        !           606:                     while (Vxl.CacheTag[LineIndex].FontId == GlyphExtended) {
        !           607:                         Vxl.CacheTag[LineIndex].FontId = FreeTag;
        !           608:                         LineIndex++;
        !           609:                     }
        !           610: 
        !           611:                     //
        !           612:                     //  Store the tag for the current glyph.
        !           613:                     //
        !           614: 
        !           615:                     Vxl.CacheTag[CacheIndex].FontId = FontId;
        !           616:                     Vxl.CacheTag[CacheIndex].GlyphHandle = GlyphHandle;
        !           617: 
        !           618:                     CacheData = Vxl.FontCacheBase + (CacheIndex << 5);
        !           619: 
        !           620:                     BitMapPtr = FontBitMap->aj;
        !           621:                     GlyphBytesPerScan = (X+7) >> 3;
        !           622:                     ShiftAmount  = (GlyphBytesPerScan-1) << 3;
        !           623: 
        !           624:                     for (LineIndex=0;LineIndex < Y; LineIndex ++) {
        !           625:                         BitMapData = 0;
        !           626:                         for (ByteIndex = 0; ByteIndex < GlyphBytesPerScan; ByteIndex++) {
        !           627: 
        !           628:                             BitMapData >>= 8;
        !           629:                             BitMapData |= ToBigEndian[*BitMapPtr++] << ShiftAmount;
        !           630:                         }
        !           631:                         *CacheData++ = BitMapData;
        !           632:                     }
        !           633: 
        !           634:                     //
        !           635:                     // If Y is bigger than 32 lines, the glyph we just cached
        !           636:                     // took more than one entry. Fix the CacheTags.
        !           637:                     //
        !           638: 
        !           639:                     for (ByteIndex = 1; LineIndex > 32 ;ByteIndex++) {
        !           640:                         Vxl.CacheTag[CacheIndex+ByteIndex].FontId = GlyphExtended;
        !           641:                         LineIndex -=32;
        !           642:                     }
        !           643: 
        !           644:                 }
        !           645: 
        !           646:                 SrcAdr = Vxl.FontCacheOffset + (CacheIndex << 7);
        !           647: 
        !           648:                 DstAdr = Vxl.JaguarScreenX * (GlyphStart->ptl.y + FontBitMap->ptlOrigin.y) +
        !           649:                          ((GlyphStart->ptl.x + FontBitMap->ptlOrigin.x) << Vxl.ColorModeShift);
        !           650: 
        !           651:                 XYCmd = Cmd | (Y << XYCMD_Y_SHIFT) | X;
        !           652: 
        !           653:                 FifoWrite(DstAdr,SrcAdr,XYCmd);
        !           654:                 GlyphStart += 1;
        !           655:             } while (GlyphStart != GlyphEnd);
        !           656:         } while (bMoreGlyphs);
        !           657:     }
        !           658: 
        !           659:     //
        !           660:     //  Draw extra rectangles using foreground brush
        !           661:     //
        !           662: 
        !           663:     if (prclExtra != (PRECTL)NULL) {
        !           664:         DrvpFillRectangle(prclExtra,pboFore->iSolidColor);
        !           665:     }
        !           666: 
        !           667: #ifdef CACHE_STATS
        !           668:     if (CharCount >= 10000) {
        !           669:         ReplacementTotal += CacheReplacement;
        !           670:         CharTotal += CharCount;
        !           671:         MissTotal += CacheMisses;
        !           672:         DISPDBG((3, "Cache Statistics for last %ld chars\n",CharCount));
        !           673:         DISPDBG((3, "Misses = %ld Rate = %ld Replacements %ld\n",
        !           674:               CacheMisses,
        !           675:               (CacheMisses*100)/CharCount,
        !           676:               CacheReplacement));
        !           677: 
        !           678:         DISPDBG((3, "Cache Statistics since begining. Total of %ld chars\n",CharTotal));
        !           679:         DISPDBG((3, "Misses = %ld Rate = %ld Replacements %ld Unused entries = %ld\n",
        !           680:               MissTotal,
        !           681:               (MissTotal*100)/CharTotal,
        !           682:               ReplacementTotal,
        !           683:               CacheUnused));
        !           684:         DISPDBG((3, "HigherFontId = %x HigherGlyphHandle = %x\n",HigherFontId,HigherGlyphHandle));
        !           685:         CharCount = 0;
        !           686:         CacheMisses = 0;
        !           687:         CacheReplacement = 0;
        !           688:     }
        !           689: 
        !           690: #endif
        !           691: 
        !           692:     //
        !           693:     //  Done with call, return
        !           694:     //
        !           695: 
        !           696:     return(TRUE);
        !           697: 
        !           698:     //
        !           699:     // Could not execute this TextOut call, pass to engine.
        !           700:     // No need to synchronize here since Eng routine will call DrvSynchronize.
        !           701:     //
        !           702: 
        !           703: 
        !           704: DevFailTextOut:
        !           705: 
        !           706:     return(EngTextOut(pso,
        !           707:                       pstro,
        !           708:                       pfo,
        !           709:                       pco,
        !           710:                       prclExtra,
        !           711:                       prclOpaque,
        !           712:                       pboFore,
        !           713:                       pboOpaque,
        !           714:                       pptlOrg,
        !           715:                       mix));
        !           716: 
        !           717: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.