29 |
29 |
30 const TInt KSessionCacheEntries = 512; |
30 const TInt KSessionCacheEntries = 512; |
31 const TInt KDefaultSlantFactor = 20480; |
31 const TInt KDefaultSlantFactor = 20480; |
32 const TInt KOneIn16Dot16FixedPointFormat = 65536; |
32 const TInt KOneIn16Dot16FixedPointFormat = 65536; |
33 |
33 |
34 #ifdef FNTSTORE_SUPPORT_FMM |
34 template<class T> |
35 class TPointerArrayBaseOffset |
35 ROffsetArray<T>::ROffsetArray() |
36 { |
36 : iOffset(0), iCount(0) |
37 public: |
37 {} |
38 TInt iCount; |
38 |
39 TAny** iEntries; |
39 template<class T> |
40 TInt iAllocated; |
40 TInt ROffsetArray<T>::Create(RHeap* aHeap, TInt aCount) |
41 TInt iGranularity; |
41 { |
42 }; |
42 if (iOffset != 0) |
43 |
43 { |
44 /*RArrayGlyphEntries*/ |
44 return KErrAlreadyExists; |
45 |
45 } |
46 inline const COpenFontGlyphTreeEntry& RArrayGlyphEntries::operator[](TInt anIndex) const |
46 TAny* p = aHeap->AllocZ(aCount * sizeof(TInt)); |
47 { |
47 if (p == NULL) |
48 return *Entry(anIndex); |
48 { |
49 } |
49 return KErrNoMemory; |
50 |
50 } |
51 inline COpenFontGlyphTreeEntry& RArrayGlyphEntries::operator[](TInt anIndex) |
51 iOffset = (TInt)p - (TInt)this; |
52 { |
52 iCount = aCount; |
53 return *const_cast<COpenFontGlyphTreeEntry*>(Entry(anIndex)); |
53 return KErrNone; |
54 } |
54 } |
55 |
55 |
56 inline const COpenFontGlyphTreeEntry* RArrayGlyphEntries::Entry(TInt anIndex) const |
56 template<class T> |
57 { |
57 void ROffsetArray<T>::Close(RHeap* aHeap) |
58 return reinterpret_cast<const COpenFontGlyphTreeEntry*>(PtrAdd(EntryMemberOffSet()[anIndex],reinterpret_cast<TInt>(this))); |
58 { |
59 } |
59 if (iOffset != 0) |
60 |
60 { |
61 inline COpenFontGlyphTreeEntry** RArrayGlyphEntries::EntryMemberOffSet() const |
61 aHeap->Free(PtrAdd(this, iOffset)); |
62 { |
62 } |
63 return reinterpret_cast<COpenFontGlyphTreeEntry**>(iEntriesOffset+reinterpret_cast<TInt>(this)); |
63 iOffset = 0; |
64 } |
64 iCount = 0; |
65 |
65 } |
66 inline TAny** RArrayGlyphEntries::EntryMember() const |
66 |
67 { |
67 template<class T> |
68 return reinterpret_cast<const TPointerArrayBaseOffset*>(this)->iEntries; |
68 TInt ROffsetArray<T>::Count() const |
69 } |
69 { |
70 |
70 return iCount; |
71 TInt RArrayGlyphEntries::Append(COpenFontGlyphTreeEntry& anEntry) |
71 } |
72 { |
72 |
73 TInt err = RArray<TInt>::Append(reinterpret_cast<TInt>(&anEntry)-reinterpret_cast<TInt>(this)); |
73 template<class T> |
74 if (err == KErrNone) |
74 T* ROffsetArray<T>::operator[](TInt aIndex) const |
75 { |
75 { |
76 iEntriesOffset=reinterpret_cast<TInt>(EntryMember())-reinterpret_cast<TInt>(this); |
76 TInt e = ((TInt*)PtrAdd(this, iOffset))[aIndex]; |
77 } |
77 return e != 0 ? (T*)PtrAdd(this, e) : NULL; |
78 return err; |
78 } |
79 } |
79 |
80 #endif // FNTSTORE_SUPPORT_FMM |
80 template<class T> |
|
81 void ROffsetArray<T>::SetAt(TInt aIndex, T* aEntry) |
|
82 { |
|
83 ((TInt*)PtrAdd(this, iOffset))[aIndex] = aEntry ? (TInt)aEntry - (TInt)this : 0; |
|
84 } |
|
85 |
81 |
86 |
82 /*COpenFontGlyphCache*/ |
87 /*COpenFontGlyphCache*/ |
83 |
88 |
84 TShapeHeader* COpenFontGlyphCache::SearchShaperCache(TInt aSessionHandle, TFontShapeFunctionParameters*& aParams) |
89 TShapeHeader* COpenFontGlyphCache::SearchShaperCache(TInt aSessionHandle, TFontShapeFunctionParameters*& aParams) |
85 { |
90 { |
374 input.iFlags = 0; |
370 input.iFlags = 0; |
375 input.iSessionHandle = aSessionHandle; |
371 input.iSessionHandle = aSessionHandle; |
376 input.iReserved1 = 0; |
372 input.iReserved1 = 0; |
377 |
373 |
378 CFontStore* thisFontStore = File()->GetFontStore(); |
374 CFontStore* thisFontStore = File()->GetFontStore(); |
379 |
375 |
380 // Create the glyph cache if it doesnt already exist. |
376 // Create the glyph cache if it doesn't already exist. |
381 // This call can only come from FBSERV |
377 // This call can only come from FBSERV |
382 if (iGlyphCache == NULL) |
378 COpenFontGlyphCache* glyphCache = GetGlyphCache(); |
383 { |
379 if (glyphCache == NULL) |
384 iGlyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache)); |
380 { |
385 if (iGlyphCache == NULL) // no memory |
381 glyphCache = (COpenFontGlyphCache*) iHeap->Alloc(sizeof(COpenFontGlyphCache)); |
386 { |
382 if (glyphCache == NULL) // no memory |
387 return NULL; |
383 { |
388 } |
384 return NULL; |
389 new(iGlyphCache) COpenFontGlyphCache; |
385 } |
390 } |
386 new (glyphCache) COpenFontGlyphCache; |
391 // If there is no sentinel present, i.e. new cache |
387 SetGlyphCache(glyphCache); |
392 if (iGlyphCache->iShaperCacheSentinel == NULL) |
388 } |
393 { |
389 // If there is no sentinel present, i.e. new cache |
394 // Create a sentinel |
390 if (glyphCache->iShaperCacheSentinel == NULL) |
395 iGlyphCache->iShaperCacheSentinel = COpenFontShaperCacheEntry::New(iHeap); |
391 { |
396 if (!iGlyphCache->iShaperCacheSentinel) |
392 // Create a sentinel |
397 { |
393 glyphCache->iShaperCacheSentinel = COpenFontShaperCacheEntry::New(iHeap); |
398 // no memory |
394 if (glyphCache->iShaperCacheSentinel == NULL) |
399 return NULL; |
395 { |
400 } |
396 // no memory |
401 iGlyphCache->iShaperCacheSentinel->iNext = iGlyphCache->iShaperCacheSentinel; |
397 return NULL; |
402 iGlyphCache->iShaperCacheSentinel->iPrevious = iGlyphCache->iShaperCacheSentinel; |
398 } |
403 iGlyphCache->iNumberOfShaperCacheEntries = 1; |
399 glyphCache->iShaperCacheSentinel->iNext = glyphCache->iShaperCacheSentinel; |
404 } |
400 glyphCache->iShaperCacheSentinel->iPrevious = glyphCache->iShaperCacheSentinel; |
405 |
401 glyphCache->iNumberOfShaperCacheEntries = 1; |
406 // Before inserting into this cache, check if it was empty. |
402 } |
407 // If empty, then increment the global cache count signifying one more cache is active |
403 |
408 if (iGlyphCache->ShaperCacheIsEmpty()) |
404 // Before inserting into this cache, check if it was empty. |
409 { |
405 // If empty, then increment the global cache count signifying one more cache is active |
410 thisFontStore->IncNumShaperCaches(); |
406 if (glyphCache->ShaperCacheIsEmpty()) |
411 } |
407 { |
|
408 thisFontStore->IncNumShaperCaches(); |
|
409 } |
412 |
410 |
413 TInt addedBytes = 0; |
411 TInt addedBytes = 0; |
414 TShapeHeader* cached_header = NULL; |
412 TShapeHeader* cached_header = NULL; |
415 |
413 |
416 // Insert a new entry and return the newly inserted TShapeHeader entry |
414 // Insert a new entry and return the newly inserted TShapeHeader entry |
417 cached_header = iGlyphCache->Insert(aSessionHandle, iHeap, input, aShapeHeader, addedBytes); |
415 cached_header = glyphCache->Insert(aSessionHandle, iHeap, input, aShapeHeader, addedBytes); |
418 if (cached_header == NULL) |
416 if (cached_header == NULL) |
419 return NULL; |
417 return NULL; |
420 |
418 |
421 // If the memory used by all the caches is greater than KMaxShaperSesssionCacheMemory, then |
419 // If the memory used by all the caches is greater than KMaxShaperSesssionCacheMemory, then |
422 // free some memory by releasing the same amount of memory that was just added |
420 // free some memory by releasing the same amount of memory that was just added |
555 //Delete the shaper |
521 //Delete the shaper |
556 delete iShaper; |
522 delete iShaper; |
557 |
523 |
558 File()->GetFontStore()->CleanupCacheOnOpenFontRemoval(this); |
524 File()->GetFontStore()->CleanupCacheOnOpenFontRemoval(this); |
559 |
525 |
560 if (iGlyphCache) |
526 COpenFontGlyphCache* glyphCache = GetGlyphCache(); |
|
527 if (glyphCache != NULL) |
561 { |
528 { |
562 COpenFontGlyphTreeEntry* next = NULL; |
529 COpenFontGlyphTreeEntry* next = NULL; |
563 #ifdef FNTSTORE_SUPPORT_FMM |
530 for (COpenFontGlyphTreeEntry* g = glyphCache->iGlyphList; g != NULL; g = next) |
564 TInt ii; |
|
565 RArrayGlyphEntries& glyphArray=iGlyphCache->iGlyphArray; |
|
566 for (ii=glyphArray.Count()-1;ii>=0;--ii) |
|
567 { |
|
568 next=&glyphArray[ii]; |
|
569 COpenFontGlyph::Delete(iHeap,next); |
|
570 } |
|
571 iGlyphCache->iGlyphArray.Close(); |
|
572 #else |
|
573 for (COpenFontGlyphTreeEntry* g = iGlyphCache->iGlyphList; g; g = next) |
|
574 { |
531 { |
575 next = g->iNext; |
532 next = g->iNext; |
576 COpenFontGlyph::Delete(iHeap, g); |
533 COpenFontGlyph::Delete(iHeap, g); |
577 } |
534 } |
578 #endif // FNTSTORE_SUPPORT_FMM |
|
579 |
535 |
580 // Delete the shaper cache as well |
536 // Delete the shaper cache as well |
581 if (iGlyphCache->iShaperCacheSentinel) |
537 if (glyphCache->iShaperCacheSentinel) |
582 { |
538 { |
583 COpenFontShaperCacheEntry* previous = NULL; |
539 COpenFontShaperCacheEntry* previous = NULL; |
584 COpenFontShaperCacheEntry* si = iGlyphCache->iShaperCacheSentinel->iPrevious; |
540 COpenFontShaperCacheEntry* si = glyphCache->iShaperCacheSentinel->iPrevious; |
585 TInt heapBefore = 0; |
541 TInt heapBefore = 0; |
586 TInt heapAfter = 0; |
542 TInt heapAfter = 0; |
587 iHeap->AllocSize(heapBefore); |
543 iHeap->AllocSize(heapBefore); |
588 while (iGlyphCache->iNumberOfShaperCacheEntries > 0) |
544 while (glyphCache->iNumberOfShaperCacheEntries > 0) |
589 { |
545 { |
590 previous = si->iPrevious; |
546 previous = si->iPrevious; |
591 COpenFontShaperCacheEntry::Delete(iHeap, si); |
547 COpenFontShaperCacheEntry::Delete(iHeap, si); |
592 si = previous; |
548 si = previous; |
593 iGlyphCache->iNumberOfShaperCacheEntries--; |
549 glyphCache->iNumberOfShaperCacheEntries--; |
594 } |
550 } |
595 iHeap->AllocSize(heapAfter); |
551 iHeap->AllocSize(heapAfter); |
596 File()->GetFontStore()->SetShaperCacheMemUsage(File()->GetFontStore()->GetShaperCacheMemUsage() - (heapBefore - heapAfter)); |
552 File()->GetFontStore()->SetShaperCacheMemUsage(File()->GetFontStore()->GetShaperCacheMemUsage() - (heapBefore - heapAfter)); |
597 File()->GetFontStore()->DecNumShaperCaches(); |
553 File()->GetFontStore()->DecNumShaperCaches(); |
598 } |
554 } |
599 |
555 |
600 iHeap->Free(iGlyphCache); |
556 iHeap->Free(glyphCache); |
601 } |
557 } |
602 if (iSessionCacheList) |
558 COpenFontSessionCacheList* sessionCacheList = SessionCacheList(); |
603 iSessionCacheList->DeleteFontGlyphs(iHeap, this); |
559 if (sessionCacheList != NULL) |
604 if (iFile) |
560 { |
605 iFile->RemoveFontFromList(this); |
561 sessionCacheList->DeleteFontGlyphs(iHeap, this); |
|
562 } |
|
563 COpenFontFile* file = File(); |
|
564 if (file != NULL) |
|
565 { |
|
566 file->RemoveFontFromList(this); |
|
567 } |
606 } |
568 } |
607 |
569 |
608 COpenFontGlyph::~COpenFontGlyph() |
570 COpenFontGlyph::~COpenFontGlyph() |
609 { |
571 { |
610 } |
572 } |
611 |
573 |
612 void COpenFontGlyph::Delete(RHeap* aHeap, COpenFontGlyph* aGlyph) |
574 void COpenFontGlyph::Delete(RHeap* aHeap, COpenFontGlyph* aGlyph) |
613 { |
575 { |
614 if (aGlyph) |
576 if (aGlyph != NULL) |
615 { |
577 { |
616 #ifdef FNTSTORE_SUPPORT_FMM |
|
617 aHeap->Free(aGlyph->Bitmap()); |
578 aHeap->Free(aGlyph->Bitmap()); |
618 #else |
|
619 aHeap->Free(aGlyph->iBitmap); |
|
620 #endif // FNTSTORE_SUPPORT_FMM |
|
621 aHeap->Free(aGlyph); |
579 aHeap->Free(aGlyph); |
622 } |
580 } |
623 } |
581 } |
624 |
582 |
625 EXPORT_C void COpenFont::operator delete(TAny *aFont) |
583 EXPORT_C void COpenFont::operator delete(TAny *aFont) |
626 { |
584 { |
627 if(aFont) |
585 if(aFont != NULL) |
628 { |
586 { |
629 COpenFont* f = (COpenFont*)aFont; |
587 COpenFont* f = (COpenFont*)aFont; |
630 if (f->iHeap) |
588 if (f->iHeap) |
631 f->iHeap->Free(aFont); |
589 f->iHeap->Free(aFont); |
632 } |
590 } |
645 |
603 |
646 @return |
604 @return |
647 ETrue if aGlyphData contains valid data (that is, if aGlyphData->Bitmap() |
605 ETrue if aGlyphData contains valid data (that is, if aGlyphData->Bitmap() |
648 and aGlyphData->Metrics() are valid), EFalse otherwise. |
606 and aGlyphData->Metrics() are valid), EFalse otherwise. |
649 */ |
607 */ |
650 #ifdef FNTSTORE_SUPPORT_FMM |
|
651 TBool COpenFont::Rasterize(TInt aSessionHandle, TInt aCode, |
608 TBool COpenFont::Rasterize(TInt aSessionHandle, TInt aCode, |
652 TOpenFontGlyphData* aGlyphData) |
609 TOpenFontGlyphData* aGlyphData) |
653 { |
610 { |
654 // create the cache if it doesn't exisit. As this call can only come from |
611 // create the cache if it doesn't exisit. As this call can only come from |
655 // FBSERV if the chunk has to be resized then no panic will happen. |
612 // FBSERV if the chunk has to be resized then no panic will happen. |
656 if (iGlyphCache == NULL) |
613 COpenFontGlyphCache* glyphCache = GetGlyphCache(); |
657 { |
614 if (glyphCache == NULL) |
658 iGlyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache)); |
615 { |
659 if (iGlyphCache == NULL) // no memory |
616 glyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache)); |
|
617 if (glyphCache == NULL) // no memory |
660 { |
618 { |
661 return EFalse; |
619 return EFalse; |
662 } |
620 } |
663 new(iGlyphCache) COpenFontGlyphCache; |
621 new(glyphCache) COpenFontGlyphCache; |
|
622 SetGlyphCache(glyphCache); |
664 } |
623 } |
665 |
624 |
666 // Look in the Font Cache |
625 // Look in the Font Cache |
667 TInt* nodeInsertPtr = NULL; |
626 TInt* nodeInsertPtr = NULL; |
668 const COpenFontGlyph* g = FontCacheGlyph(aCode, nodeInsertPtr); |
627 const COpenFontGlyph* g = FontCacheGlyph(aCode, nodeInsertPtr); |
669 |
628 |
670 // If it is not found there look in the session cache. |
629 // If it is not found there look in the session cache. |
671 COpenFontSessionCache* cache = NULL; |
630 COpenFontSessionCache* cache = NULL; |
672 TInt index = 0; |
631 TInt index = 0; |
673 if (!g) |
632 if (g == NULL) |
674 { |
633 { |
675 g = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, EFalse); |
634 g = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, EFalse); |
676 } |
635 } |
677 |
636 |
678 // If it has already been rasterized return it. |
637 // If it has already been rasterized return it. |
679 if (g) |
638 if (g != NULL) |
680 { |
639 { |
681 if (aGlyphData) |
640 if (aGlyphData != NULL) |
682 { |
641 { |
683 aGlyphData->SetMetricsPointer(&g->iMetrics); |
642 aGlyphData->SetMetricsPointer(&g->iMetrics); |
684 aGlyphData->SetBitmapPointer(g->Bitmap()); |
643 aGlyphData->SetBitmapPointer(g->Bitmap()); |
685 } |
644 } |
686 |
645 |
701 const TOpenFontGlyphData* cur_glyph_data = temp_glyph_data ? temp_glyph_data : aGlyphData; |
660 const TOpenFontGlyphData* cur_glyph_data = temp_glyph_data ? temp_glyph_data : aGlyphData; |
702 const COpenFontGlyph* new_glyph = NULL; |
661 const COpenFontGlyph* new_glyph = NULL; |
703 |
662 |
704 // If the maximum per-font cache memory will not be exceeded, put the glyph into the font cache. |
663 // If the maximum per-font cache memory will not be exceeded, put the glyph into the font cache. |
705 TInt bytes = sizeof(COpenFontGlyphTreeEntry) + cur_glyph_data->BytesNeeded(); |
664 TInt bytes = sizeof(COpenFontGlyphTreeEntry) + cur_glyph_data->BytesNeeded(); |
706 if(iGlyphCache && bytes + iGlyphCache->iGlyphCacheMemory <= KMaxGlyphCacheMemory) |
665 if(glyphCache != NULL && bytes + glyphCache->iGlyphCacheMemory <= KMaxGlyphCacheMemory) |
707 { |
666 { |
708 COpenFontGlyphTreeEntry* new_entry = COpenFontGlyphTreeEntry::New(iHeap, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap()); |
667 COpenFontGlyphTreeEntry* new_entry = COpenFontGlyphTreeEntry::New(iHeap, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap()); |
709 new_glyph=new_entry; |
668 new_glyph=new_entry; |
710 if(new_entry) |
669 if (new_entry != NULL) |
711 { |
670 { |
712 // Insert new entry into the delete list |
671 // Add the glyph to a leaf node using the nodeInsertPtr that was returned by FontCacheGlyph() |
713 error = iGlyphCache->iGlyphArray.Append(*new_entry); |
672 // This is the first node if the glyph cache is empty. This updates the cache atomically. |
714 if (error == KErrNone) |
673 *nodeInsertPtr = PointerToThisOffset(new_entry); |
715 { |
674 |
716 if(!iGlyphCache->iGlyphTreeOffset) |
675 // If new_entry is not the first in the cache, set the previous |
717 { |
676 // entry to link to this so that a linked-list of entries can be |
718 // First entry in tree |
677 // maintained to simplify deletion. |
719 iGlyphCache->iGlyphTreeOffset = PointerToThisOffset(new_entry); |
678 COpenFontGlyphTreeEntry* tree = static_cast<COpenFontGlyphTreeEntry*> (ThisOffsetToPointer(glyphCache->iGlyphTreeOffset)); |
720 } |
679 if (new_entry != tree) |
721 else if (nodeInsertPtr) |
680 { |
722 { |
681 while (tree->iNext != NULL) |
723 // Add the glyph to a leaf node using the nodeInsertPtr that was returned by FontCacheGlyph() |
682 { |
724 *nodeInsertPtr = PointerToThisOffset(new_entry); |
683 tree = tree->iNext; |
725 } |
684 } |
726 else |
685 tree->iNext = new_entry; |
727 { |
686 } |
728 // Failed to add the glyph to the glyph tree, remove it from the delete array. |
687 else |
729 // (The glyph is deleted below). |
688 { |
730 iGlyphCache->iGlyphArray.Remove(iGlyphCache->iGlyphArray.Count()-1); |
689 // First entry in tree, initialise iGlyphList |
731 error = KErrGeneral; |
690 glyphCache->iGlyphList = new_entry; |
732 } |
691 } |
733 } |
692 |
734 if (error != KErrNone) |
693 glyphCache->iGlyphCacheMemory += bytes; |
735 { |
694 }//if (new_entry) |
736 COpenFontGlyph::Delete(iHeap,new_entry); |
|
737 } |
|
738 else |
|
739 { |
|
740 iGlyphCache->iGlyphCacheMemory += bytes; |
|
741 } |
|
742 } |
|
743 } |
695 } |
744 else |
696 else |
745 { |
697 { |
746 error = KErrGeneral; |
698 error = KErrGeneral; |
747 } |
699 } |
748 |
700 |
749 // Otherwise put the glyph into the per-session cache. |
701 // Otherwise put the glyph into the per-session cache. |
750 if (error != KErrNone) |
702 if (error != KErrNone) |
751 { |
703 { |
752 // If the session cache is not yet known find it or create one. |
704 // If the session cache is not yet known find it or create one. |
753 if (!cache) |
705 if (cache == NULL) |
754 { |
706 { |
755 SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, TRUE); |
707 SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, TRUE); |
756 } |
708 } |
757 if (!cache) |
709 if (cache == NULL) |
758 { |
710 { |
759 return EFalse; |
711 return EFalse; |
760 } |
712 } |
761 |
713 |
762 COpenFontSessionCacheEntry* new_entry = |
714 COpenFontSessionCacheEntry* new_entry = |
763 COpenFontSessionCacheEntry::New(iHeap, this, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap()); |
715 COpenFontSessionCacheEntry::New(iHeap, this, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap()); |
764 new_glyph = new_entry; |
716 new_glyph = new_entry; |
765 if (new_entry) |
717 if (new_entry != NULL) |
766 { |
718 { |
767 cache->Insert(iHeap, new_entry, index); |
719 cache->Insert(iHeap, new_entry, index); |
768 } |
720 } |
769 } |
721 } |
770 |
722 |
771 if (temp_glyph_data) |
723 if (temp_glyph_data != NULL) |
772 { |
724 { |
773 iHeap->Free(temp_glyph_data); |
725 iHeap->Free(temp_glyph_data); |
774 } |
726 } |
775 |
727 |
776 // Fix up the returned glyph data pointers to point to the actual data. |
728 // Fix up the returned glyph data pointers to point to the actual data. |
777 if (!new_glyph) |
729 if (new_glyph == NULL) |
778 glyph_data_valid = FALSE; |
730 glyph_data_valid = EFalse; |
779 else if (aGlyphData) |
731 else if (aGlyphData != NULL) |
780 { |
732 { |
781 aGlyphData->SetMetricsPointer(&new_glyph->iMetrics); |
733 aGlyphData->SetMetricsPointer(&new_glyph->iMetrics); |
782 aGlyphData->SetBitmapPointer(new_glyph->Bitmap()); |
734 aGlyphData->SetBitmapPointer(new_glyph->Bitmap()); |
783 } |
735 } |
784 |
736 |
785 return glyph_data_valid; |
737 return glyph_data_valid; |
786 } |
738 } |
787 #else |
|
788 TBool COpenFont::Rasterize(TInt aSessionHandle, TInt aCode, |
|
789 TOpenFontGlyphData* aGlyphData) |
|
790 { |
|
791 // First look in the font cache. |
|
792 COpenFontGlyphTreeEntry** node_ptr = NULL; |
|
793 // create the cache if it doesn't exisit. As this call can only come from |
|
794 // FBSERV if the chunk has to be resized then no panic will happen. |
|
795 if (iGlyphCache == NULL) |
|
796 { |
|
797 iGlyphCache = (COpenFontGlyphCache*)iHeap->Alloc(sizeof(COpenFontGlyphCache)); |
|
798 if (iGlyphCache == NULL) // no memory |
|
799 { |
|
800 return FALSE; |
|
801 } |
|
802 new(iGlyphCache) COpenFontGlyphCache; |
|
803 } |
|
804 |
|
805 // Look in the fontcache. Do not expect to find a glyph here. However, |
|
806 // it is called again so that a node pointer is found where the new glyph |
|
807 // will be placed when added to the font cache. |
|
808 const COpenFontGlyph* glyph = FontCacheGlyph(aCode, node_ptr); |
|
809 if (glyph) |
|
810 { |
|
811 // Do not expect it to get here, since the font cache has already been searched client-side, |
|
812 // prior to calling Rasterize(). However, just in case it does find a match, use it. |
|
813 if (aGlyphData) |
|
814 { |
|
815 aGlyphData->SetMetricsPointer(&glyph->iMetrics); |
|
816 aGlyphData->SetBitmapPointer(glyph->iBitmap); |
|
817 } |
|
818 return TRUE; |
|
819 } |
|
820 |
|
821 // Rasterize the glyph. |
|
822 TOpenFontGlyphData* temp_glyph_data = NULL; |
|
823 TInt error = KErrNone; |
|
824 TRAP(error, RasterizeHelperL(aCode, aGlyphData, temp_glyph_data)); |
|
825 if (error) |
|
826 { |
|
827 iHeap->Free(temp_glyph_data); |
|
828 return FALSE; |
|
829 } |
|
830 |
|
831 TBool glyph_data_valid = TRUE; |
|
832 const TOpenFontGlyphData* cur_glyph_data = temp_glyph_data ? temp_glyph_data : aGlyphData; |
|
833 const COpenFontGlyph* new_glyph = NULL; |
|
834 |
|
835 // If the maximum per-font cache memory will not be exceeded, put the glyph into the font cache. |
|
836 TInt bytes = sizeof(COpenFontGlyphTreeEntry) + cur_glyph_data->BytesNeeded(); |
|
837 if (iGlyphCache && node_ptr && bytes + iGlyphCache->iGlyphCacheMemory <= KMaxGlyphCacheMemory) |
|
838 { |
|
839 COpenFontGlyphTreeEntry* new_entry = COpenFontGlyphTreeEntry::New(iHeap, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap()); |
|
840 new_glyph = new_entry; |
|
841 if (new_entry) |
|
842 { |
|
843 *node_ptr = new_entry; // update the cache atomically |
|
844 |
|
845 // Insert new entry into the delete list |
|
846 |
|
847 COpenFontGlyphTreeEntry* start = iGlyphCache->iGlyphTree; |
|
848 COpenFontGlyphTreeEntry* tree = start; |
|
849 |
|
850 if (new_entry != iGlyphCache->iGlyphTree) |
|
851 { |
|
852 while (tree->iNext) |
|
853 { |
|
854 tree = tree->iNext; |
|
855 } |
|
856 tree->iNext = new_entry; |
|
857 } |
|
858 else |
|
859 { |
|
860 // First entry in tree, initialise iGlyphList |
|
861 iGlyphCache->iGlyphList = new_entry; |
|
862 } |
|
863 |
|
864 iGlyphCache->iGlyphCacheMemory += bytes; |
|
865 } |
|
866 } |
|
867 |
|
868 // Otherwise put the glyph into the per-session cache. |
|
869 else |
|
870 { |
|
871 // If the session cache is not yet known find it or create one. |
|
872 COpenFontSessionCache* cache = NULL; |
|
873 TInt index = 0; |
|
874 SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, TRUE); |
|
875 if (!cache) |
|
876 return FALSE; |
|
877 COpenFontSessionCacheEntry* new_entry = |
|
878 COpenFontSessionCacheEntry::New(iHeap, this, aCode, cur_glyph_data->GlyphIndex(), *cur_glyph_data->Metrics(), cur_glyph_data->Bitmap()); |
|
879 new_glyph = new_entry; |
|
880 if (new_entry) |
|
881 cache->Insert(iHeap, new_entry, index); |
|
882 } |
|
883 |
|
884 if (temp_glyph_data) |
|
885 { |
|
886 iHeap->Free(temp_glyph_data); |
|
887 } |
|
888 |
|
889 // Fix up the returned glyph data pointers to point to the actual data. |
|
890 if (!new_glyph) |
|
891 glyph_data_valid = FALSE; |
|
892 else if (aGlyphData) |
|
893 { |
|
894 aGlyphData->SetMetricsPointer(&new_glyph->iMetrics); |
|
895 aGlyphData->SetBitmapPointer(new_glyph->iBitmap); |
|
896 } |
|
897 |
|
898 return glyph_data_valid; |
|
899 } |
|
900 #endif // FNTSTORE_SUPPORT_FMM |
|
901 |
739 |
902 void COpenFont::RasterizeHelperL(TInt aCode, TOpenFontGlyphData* aGlyphData, TOpenFontGlyphData*& aTempGlyphData) |
740 void COpenFont::RasterizeHelperL(TInt aCode, TOpenFontGlyphData* aGlyphData, TOpenFontGlyphData*& aTempGlyphData) |
903 { |
741 { |
904 aTempGlyphData = 0; |
742 aTempGlyphData = 0; |
905 MOpenFontShapingExtension* extensionInterface = 0; |
743 MOpenFontShapingExtension* extensionInterface = 0; |
1099 aMetrics.iAscentInPixels = iHorizBearingY; |
936 aMetrics.iAscentInPixels = iHorizBearingY; |
1100 aMetrics.iHeightInPixels = iHeight; |
937 aMetrics.iHeightInPixels = iHeight; |
1101 aMetrics.iLeftAdjustInPixels = iHorizBearingX; |
938 aMetrics.iLeftAdjustInPixels = iHorizBearingX; |
1102 aMetrics.iMoveInPixels = iHorizAdvance; |
939 aMetrics.iMoveInPixels = iHorizAdvance; |
1103 aMetrics.iRightAdjustInPixels = (TInt16)(iHorizAdvance - iHorizBearingX - iWidth); |
940 aMetrics.iRightAdjustInPixels = (TInt16)(iHorizAdvance - iHorizBearingX - iWidth); |
1104 return TRUE; |
941 return ETrue; |
1105 } |
942 } |
1106 |
943 |
1107 TBool COpenFont::GetCharacterData(TInt aSessionHandle, TInt aCode, const TOpenFontCharMetrics*& aMetrics, const TUint8*& aBitmap) const |
944 TBool COpenFont::GetCharacterData(TInt aSessionHandle, TInt aCode, const TOpenFontCharMetrics*& aMetrics, const TUint8*& aBitmap) const |
1108 { |
945 { |
1109 const COpenFontGlyph* g = Glyph(aSessionHandle, aCode); |
946 const COpenFontGlyph* g = Glyph(aSessionHandle, aCode); |
1110 if (g) |
947 if (g != NULL) |
1111 { |
948 { |
1112 aMetrics = &g->iMetrics; |
949 aMetrics = &g->iMetrics; |
1113 #ifdef FNTSTORE_SUPPORT_FMM |
|
1114 aBitmap = g->Bitmap(); |
950 aBitmap = g->Bitmap(); |
1115 #else |
951 return ETrue; |
1116 aBitmap = g->iBitmap; |
|
1117 #endif // FNTSTORE_SUPPORT_FMM |
|
1118 return TRUE; |
|
1119 } |
952 } |
1120 else |
953 else |
1121 { |
954 { |
1122 aMetrics = NULL; |
955 aMetrics = NULL; |
1123 aBitmap = NULL; |
956 aBitmap = NULL; |
1124 return FALSE; |
957 return EFalse; |
1125 } |
958 } |
1126 } |
959 } |
1127 |
960 |
1128 |
961 |
1129 |
962 |
1130 void COpenFont::OnFileDeleted() |
963 void COpenFont::OnFileDeleted() |
1131 { |
964 { |
1132 iFile = NULL; |
965 iFileOffset = 0; |
1133 } |
966 } |
1134 |
967 |
1135 COpenFontGlyphCache* COpenFont::GetGlyphCache() |
968 COpenFontGlyphCache* COpenFont::GetGlyphCache() |
1136 { |
969 { |
1137 #ifdef FNTSTORE_SUPPORT_FMM |
970 if (iGlyphCacheOffset == 0) |
1138 if (iGlyphCache) |
971 { |
1139 return reinterpret_cast<COpenFontGlyphCache*>(reinterpret_cast<TInt>(iGlyphCache)+Offset()); |
972 return NULL; |
1140 #else |
973 } |
1141 if (iGlyphCache) |
974 return reinterpret_cast<COpenFontGlyphCache*>(PtrAdd(this, iGlyphCacheOffset)); |
1142 return iGlyphCache; |
|
1143 #endif // FNTSTORE_SUPPORT_FMM |
|
1144 else |
|
1145 return NULL; |
|
1146 } |
975 } |
1147 |
976 |
1148 const COpenFontGlyph* COpenFont::Glyph(TInt aSessionHandle, TInt aCode) const |
977 const COpenFontGlyph* COpenFont::Glyph(TInt aSessionHandle, TInt aCode) const |
1149 { |
978 { |
1150 #ifdef FNTSTORE_SUPPORT_FMM |
|
1151 const COpenFontGlyph* glyph = const_cast<COpenFont*>(this)->FontCacheGlyph(aCode); |
979 const COpenFontGlyph* glyph = const_cast<COpenFont*>(this)->FontCacheGlyph(aCode); |
1152 if (!glyph) |
980 if (glyph == NULL) |
1153 { |
981 { |
1154 COpenFontSessionCache* cache; |
982 COpenFontSessionCache* cache; |
1155 TInt index; |
983 TInt index; |
1156 glyph = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, FALSE); |
984 glyph = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, EFalse); |
1157 } |
985 } |
1158 |
986 |
1159 return glyph; |
987 return glyph; |
1160 #else |
|
1161 const COpenFontGlyph* g = CONST_CAST(COpenFont*,this)->FontCacheGlyph(aCode); |
|
1162 if (!g) |
|
1163 { |
|
1164 COpenFontSessionCache* cache; |
|
1165 TInt index; |
|
1166 g = SessionCacheGlyph(iHeap, aSessionHandle, aCode, cache, index, FALSE); |
|
1167 } |
|
1168 return g; |
|
1169 #endif // FNTSTORE_SUPPORT_FMM |
|
1170 } |
988 } |
1171 |
989 |
1172 /** |
990 /** |
1173 Is the specified character present in the font? |
991 Is the specified character present in the font? |
1174 */ |
992 */ |
1175 TBool COpenFont::HasCharacterL(TInt aCode) const |
993 TBool COpenFont::HasCharacterL(TInt aCode) const |
1176 { |
994 { |
1177 COpenFontFile* file = File(); |
995 COpenFontFile* file = File(); |
1178 if (file) |
996 if (file != NULL) |
1179 return file->HasUnicodeCharacterL(iFaceIndex, aCode); |
997 return file->HasUnicodeCharacterL(iFaceIndex, aCode); |
1180 else |
998 else |
1181 return FALSE; |
999 return EFalse; |
1182 } |
1000 } |
1183 |
1001 |
1184 #ifdef FNTSTORE_SUPPORT_FMM |
|
1185 /** |
1002 /** |
1186 Retrieve glyph data from the per-font glyph cache. |
1003 Retrieve glyph data from the per-font glyph cache. |
1187 If it is not found return NULL. |
1004 If it is not found return NULL. |
1188 If the cache hasn't been created, then return NULL. |
1005 If the cache hasn't been created, then return NULL. |
1189 Previous versions of this function created the cache, but as this function can potentially |
1006 Previous versions of this function created the cache, but as this function can potentially |
1424 aIndex = GLYPH_CODE(aCode) % KSessionCacheEntries; |
1183 aIndex = GLYPH_CODE(aCode) % KSessionCacheEntries; |
1425 } |
1184 } |
1426 } |
1185 } |
1427 return NULL; |
1186 return NULL; |
1428 } |
1187 } |
1429 #else |
1188 |
1430 const COpenFontGlyph* COpenFont::SessionCacheGlyph(RHeap* aHeap, |
1189 COpenFontSessionCacheList* COpenFont::SessionCacheList()const |
1431 TInt aSessionHandle, TInt aCode, COpenFontSessionCache*& aCache, |
1190 { |
1432 TInt& aIndex, TBool aCreate) const |
1191 if (iSessionCacheListOffset == 0) |
1433 { |
|
1434 aCache = NULL; |
|
1435 aIndex = 0; |
|
1436 COpenFontSessionCacheListItem* prev = NULL; |
|
1437 RSemaphore sem; |
|
1438 if(KErrNone != sem.OpenGlobal(KSessionCacheSemaphoreName)) |
|
1439 { |
1192 { |
1440 RDebug::Print(_L("COpenFont::SessionCacheGlyphe() can't open SessionCacheSemaphore")); |
|
1441 return NULL; |
1193 return NULL; |
1442 } |
1194 } |
1443 sem.Wait(); |
1195 return reinterpret_cast<COpenFontSessionCacheList*>(reinterpret_cast<TInt>(this) + iSessionCacheListOffset); |
1444 for (COpenFontSessionCacheListItem* p = iSessionCacheList->iStart; p; p = p->iNext) |
1196 } |
1445 { |
1197 |
1446 if (p->iCache->iSessionHandle == aSessionHandle) |
1198 void COpenFont::SetSessionCacheList(COpenFontSessionCacheList* aSessionCacheList) |
1447 { |
1199 { |
1448 aCache = p->iCache; |
1200 iSessionCacheListOffset = aSessionCacheList ? reinterpret_cast<TInt>(aSessionCacheList) - reinterpret_cast<TInt>(this) : NULL; |
1449 sem.Signal(); |
1201 } |
1450 sem.Close(); |
1202 |
1451 return aCache->Glyph(this, aCode, aIndex); |
1203 void COpenFont::SetFile(COpenFontFile* aFile) |
1452 } |
1204 { |
1453 prev = p; |
1205 iFileOffset = aFile ? reinterpret_cast<TInt>(aFile) - reinterpret_cast<TInt>(this) : NULL; |
1454 } |
1206 } |
1455 sem.Signal(); |
1207 |
1456 sem.Close(); |
1208 void COpenFont::SetGlyphCache(COpenFontGlyphCache* aGlyphCache) |
1457 |
1209 { |
1458 if (aCreate) |
1210 iGlyphCacheOffset = aGlyphCache ? reinterpret_cast<TInt>(aGlyphCache) - reinterpret_cast<TInt>(this) : NULL; |
1459 { |
1211 } |
1460 COpenFontSessionCache* new_cache = NULL; |
1212 |
1461 TRAPD(error, new_cache = COpenFontSessionCache::NewL(aHeap, aSessionHandle, KSessionCacheEntries)); |
|
1462 |
|
1463 if ((!error) && new_cache) |
|
1464 { |
|
1465 COpenFontSessionCacheListItem* new_item = (COpenFontSessionCacheListItem*)aHeap->Alloc(sizeof(COpenFontSessionCacheListItem)); |
|
1466 if (!new_item) |
|
1467 { |
|
1468 new_cache->Delete(aHeap); |
|
1469 aHeap->Free(new_cache); |
|
1470 return NULL; |
|
1471 } |
|
1472 |
|
1473 new(new_item) COpenFontSessionCacheListItem(new_cache); |
|
1474 |
|
1475 if (prev) |
|
1476 prev->iNext = new_item; |
|
1477 else |
|
1478 iSessionCacheList->iStart = new_item; |
|
1479 |
|
1480 aCache = new_cache; |
|
1481 aIndex = GLYPH_CODE(aCode) % KSessionCacheEntries; |
|
1482 } |
|
1483 } |
|
1484 return NULL; |
|
1485 } |
|
1486 #endif // FNTSTORE_SUPPORT_FMM |
|
1487 |
1213 |
1488 /** |
1214 /** |
1489 Create a glyph data object on the shared heap, given the code, metrics and the data bytes. |
1215 Create a glyph data object on the shared heap, given the code, metrics and the data bytes. |
1490 The data is copied; ownership remains with the caller. |
1216 The data is copied; ownership remains with the caller. |
1491 */ |
1217 */ |
1516 } |
1242 } |
1517 |
1243 |
1518 COpenFontSessionCacheEntry* COpenFontSessionCacheEntry::New(RHeap* aHeap, const COpenFont* aFont, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap) |
1244 COpenFontSessionCacheEntry* COpenFontSessionCacheEntry::New(RHeap* aHeap, const COpenFont* aFont, TInt aCode, TInt aGlyphIndex, const TOpenFontCharMetrics& aMetrics, const TDesC8& aBitmap) |
1519 { |
1245 { |
1520 COpenFontSessionCacheEntry* entry = (COpenFontSessionCacheEntry*)aHeap->Alloc(sizeof(COpenFontSessionCacheEntry)); |
1246 COpenFontSessionCacheEntry* entry = (COpenFontSessionCacheEntry*)aHeap->Alloc(sizeof(COpenFontSessionCacheEntry)); |
1521 if (!entry) |
1247 if (entry == NULL) |
1522 return NULL; |
1248 return NULL; |
1523 new(entry) COpenFontSessionCacheEntry(aFont, aCode, aGlyphIndex, aMetrics); |
1249 new(entry) COpenFontSessionCacheEntry(aFont, aCode, aGlyphIndex, aMetrics); |
1524 if (!entry->SetBitmap(aHeap, aBitmap)) |
1250 if (!entry->SetBitmap(aHeap, aBitmap)) |
1525 { |
1251 { |
1526 aHeap->Free(entry); |
1252 aHeap->Free(entry); |
1527 entry = NULL; |
1253 entry = NULL; |
1528 } |
1254 } |
1529 return entry; |
1255 return entry; |
1530 } |
1256 } |
1531 |
|
1532 #ifdef FNTSTORE_SUPPORT_FMM |
|
1533 |
|
1534 inline COpenFont* COpenFontSessionCacheEntry::Font()const |
|
1535 { |
|
1536 if(iFontOffset) |
|
1537 { |
|
1538 return reinterpret_cast<COpenFont*>(reinterpret_cast<TInt>(this) + iFontOffset); |
|
1539 } |
|
1540 else |
|
1541 return NULL; |
|
1542 } |
|
1543 |
1257 |
1544 /** |
1258 /** |
1545 @return A pointer to the run-length-encoded bitmap stored with this glyph, or NULL |
1259 @return A pointer to the run-length-encoded bitmap stored with this glyph, or NULL |
1546 if no bitmap has been stored with this glyph. |
1260 if no bitmap has been stored with this glyph. |
1547 */ |
1261 */ |
1548 TUint8* COpenFontGlyph::Bitmap() const |
1262 TUint8* COpenFontGlyph::Bitmap() const |
1549 { |
1263 { |
1550 if (iBitmapOffset) |
1264 if (iBitmapOffset) |
1551 { |
1265 { |
1552 return (TUint8*)((TInt)this + iBitmapOffset); |
1266 return reinterpret_cast<TUint8*>(reinterpret_cast<TInt>(this) + iBitmapOffset); |
1553 } |
1267 } |
1554 return NULL; |
1268 return NULL; |
1555 } |
1269 } |
1556 #endif // FNTSTORE_SUPPORT_FMM |
|
1557 |
1270 |
1558 TBool COpenFontGlyph::SetBitmap(RHeap* aHeap, const TDesC8& aBitmap) |
1271 TBool COpenFontGlyph::SetBitmap(RHeap* aHeap, const TDesC8& aBitmap) |
1559 { |
1272 { |
1560 TUint8* bitmap = (TUint8*)aHeap->Alloc(aBitmap.Length()); |
1273 TUint8* bitmap = (TUint8*)aHeap->Alloc(aBitmap.Length()); |
1561 if (!bitmap) |
1274 if (bitmap == NULL) |
1562 return FALSE; |
1275 return EFalse; |
1563 Mem::Copy(bitmap, aBitmap.Ptr(), aBitmap.Length()); |
1276 Mem::Copy(bitmap, aBitmap.Ptr(), aBitmap.Length()); |
1564 #ifdef FNTSTORE_SUPPORT_FMM |
|
1565 aHeap->Free(Bitmap()); |
1277 aHeap->Free(Bitmap()); |
1566 iBitmapOffset = (TInt)bitmap - (TInt)this; |
1278 iBitmapOffset = reinterpret_cast<TInt>(bitmap) - reinterpret_cast<TInt>(this); |
1567 #else |
1279 return ETrue; |
1568 if (iBitmap) |
1280 } |
1569 aHeap->Free(iBitmap); |
1281 |
1570 iBitmap = bitmap; |
|
1571 #endif // FNTSTORE_SUPPORT_FMM |
|
1572 return TRUE; |
|
1573 } |
|
1574 #ifdef FNTSTORE_SUPPORT_FMM |
|
1575 COpenFontSessionCache* COpenFontSessionCache::NewL(RHeap* aHeap, TInt aSessionHandle, TInt aEntries) |
1282 COpenFontSessionCache* COpenFontSessionCache::NewL(RHeap* aHeap, TInt aSessionHandle, TInt aEntries) |
1576 { |
1283 { |
1577 COpenFontSessionCache* c = reinterpret_cast<COpenFontSessionCache*>(aHeap->AllocL(sizeof(COpenFontSessionCache))); |
|
1578 new(c) COpenFontSessionCache(aSessionHandle,aEntries); |
|
1579 TInt bytes = sizeof(TInt) * aEntries; |
|
1580 TInt* entry= reinterpret_cast<TInt*>(aHeap->Alloc(bytes)); |
|
1581 Mem::FillZ(entry, bytes); |
|
1582 if (!entry) |
|
1583 { |
|
1584 aHeap->Free(c); |
|
1585 User::Leave(KErrNoMemory); |
|
1586 } |
|
1587 c->iEntryOffset = reinterpret_cast<TInt>(entry) - reinterpret_cast<TInt>(c); |
|
1588 return c; |
|
1589 } |
|
1590 #else |
|
1591 COpenFontSessionCache* COpenFontSessionCache::NewL(RHeap* aHeap, TInt aSessionHandle, TInt aEntries) |
|
1592 { |
|
1593 COpenFontSessionCache* c = (COpenFontSessionCache*)aHeap->AllocL(sizeof(COpenFontSessionCache)); |
1284 COpenFontSessionCache* c = (COpenFontSessionCache*)aHeap->AllocL(sizeof(COpenFontSessionCache)); |
1594 new(c) COpenFontSessionCache(aSessionHandle,aEntries); |
1285 new(c) COpenFontSessionCache(aSessionHandle); |
1595 TInt bytes = sizeof(COpenFontSessionCacheEntry*) * aEntries; |
1286 if (c->iEntryArray.Create(aHeap, aEntries) != KErrNone) |
1596 c->iEntry = (COpenFontSessionCacheEntry**)aHeap->Alloc(bytes); |
|
1597 Mem::FillZ(c->iEntry, bytes); |
|
1598 if (!c->iEntry) |
|
1599 { |
1287 { |
1600 aHeap->Free(c); |
1288 aHeap->Free(c); |
1601 User::Leave(KErrNoMemory); |
1289 User::Leave(KErrNoMemory); |
1602 } |
1290 } |
1603 return c; |
1291 return c; |
1604 } |
1292 } |
1605 #endif //FNTSTORE_SUPPORT_FMM |
1293 |
1606 |
1294 |
1607 #ifdef FNTSTORE_SUPPORT_FMM |
|
1608 void COpenFontSessionCache::Delete(RHeap* aHeap) |
1295 void COpenFontSessionCache::Delete(RHeap* aHeap) |
1609 { |
1296 { |
1610 TInt* e =Entry(); |
1297 TInt entries = iEntryArray.Count(); |
1611 if(e) |
1298 for (TInt i = 0; i < entries; ++i) |
1612 { |
1299 { |
1613 for (TInt i = 0; i < iEntries; i++, e++) |
1300 COpenFontSessionCacheEntry* e = iEntryArray[i]; |
|
1301 if (e != NULL) |
1614 { |
1302 { |
1615 if (ToCOpenFontSessionCacheEntryPointer(*e)) |
1303 COpenFont* font=const_cast<COpenFont*>(e->Font()); |
|
1304 if (font != NULL) |
|
1305 font->DecrementCachedRefCount(iSessionHandle,NULL,ETrue); |
|
1306 aHeap->Free(e->Bitmap()); |
|
1307 aHeap->Free(e); |
|
1308 } |
|
1309 } |
|
1310 iEntryArray.Close(aHeap); |
|
1311 } |
|
1312 |
|
1313 const COpenFontGlyph* COpenFontSessionCache::Glyph(const COpenFont* aFont, TInt aCode, TInt& aIndex) |
|
1314 { |
|
1315 aIndex = -1; |
|
1316 TInt oldest = KMaxTInt; |
|
1317 TInt oldest_index = 0; |
|
1318 TInt entries = iEntryArray.Count(); |
|
1319 TInt index = GLYPH_CODE(aCode) % entries; // simple hash function to shorten searches |
|
1320 for (TInt i = 0; i < entries; ++i, ++index) |
|
1321 { |
|
1322 if (index >= entries) |
|
1323 index = 0; |
|
1324 COpenFontSessionCacheEntry* e = iEntryArray[index]; |
|
1325 if (e == NULL) |
|
1326 { |
|
1327 if (aIndex == -1) |
|
1328 aIndex = index; |
|
1329 } |
|
1330 else |
|
1331 { |
|
1332 if (e->Font() == aFont && e->iCode == aCode) |
1616 { |
1333 { |
1617 COpenFont* font=const_cast<COpenFont*>((ToCOpenFontSessionCacheEntryPointer(*e))->Font()); |
1334 e->iLastAccess = iLastAccess++; |
1618 if (font) |
1335 return e; |
1619 font->DecrementCachedRefCount(iSessionHandle, NULL, ETrue); |
1336 } |
1620 aHeap->Free((ToCOpenFontSessionCacheEntryPointer(*e))->Bitmap()); |
1337 if (e->iLastAccess < oldest) |
1621 aHeap->Free(ToCOpenFontSessionCacheEntryPointer(*e)); |
1338 { |
|
1339 oldest = e->iLastAccess; |
|
1340 oldest_index = index; |
1622 } |
1341 } |
1623 } |
1342 } |
1624 aHeap->Free(Entry()); |
|
1625 iEntryOffset = 0; |
|
1626 } |
1343 } |
|
1344 if (aIndex == -1) |
|
1345 aIndex = oldest_index; |
|
1346 return NULL; |
|
1347 } |
|
1348 |
|
1349 |
|
1350 void COpenFontSessionCache::Insert(RHeap* aHeap, COpenFontSessionCacheEntry* aEntry, TInt aIndex) |
|
1351 { |
|
1352 if (aIndex < 0 || aIndex >= iEntryArray.Count()) |
|
1353 Panic(EFntSessionCacheIndexOutOfRange); |
|
1354 COpenFontGlyph::Delete(aHeap, iEntryArray[aIndex]); |
|
1355 iEntryArray.SetAt(aIndex, aEntry); |
|
1356 aEntry->iLastAccess = iLastAccess++; |
|
1357 } |
|
1358 |
|
1359 COpenFontSessionCache::COpenFontSessionCache(TInt aSessionHandle): |
|
1360 iSessionHandle(aSessionHandle), |
|
1361 iLastAccess(0) |
|
1362 { |
1627 } |
1363 } |
1628 #else |
|
1629 void COpenFontSessionCache::Delete(RHeap* aHeap) |
|
1630 { |
|
1631 COpenFontSessionCacheEntry** e =iEntry; |
|
1632 for (TInt i = 0; i < iEntries; i++, e++) |
|
1633 { |
|
1634 if (*e) |
|
1635 { |
|
1636 COpenFont* font=const_cast<COpenFont*>((*e)->iFont); |
|
1637 if (font) |
|
1638 font->DecrementCachedRefCount(iSessionHandle, NULL, ETrue); |
|
1639 aHeap->Free((*e)->iBitmap); |
|
1640 aHeap->Free(*e); |
|
1641 } |
|
1642 } |
|
1643 aHeap->Free(iEntry); |
|
1644 } |
|
1645 #endif //FNTSTORE_SUPPORT_FMM |
|
1646 |
|
1647 const COpenFontGlyph* COpenFontSessionCache::Glyph(const COpenFont* aFont, TInt aCode, TInt& aIndex) |
|
1648 { |
|
1649 aIndex = -1; |
|
1650 TInt oldest = KMaxTInt; |
|
1651 TInt oldest_index = 0; |
|
1652 TInt index = GLYPH_CODE(aCode) % iEntries; // simple hash function to shorten searches |
|
1653 for (TInt i = 0; i < iEntries; i++, index++) |
|
1654 { |
|
1655 if (index >= iEntries) |
|
1656 index = 0; |
|
1657 #ifdef FNTSTORE_SUPPORT_FMM |
|
1658 COpenFontSessionCacheEntry* e = ToCOpenFontSessionCacheEntryPointer(Entry()[index]); |
|
1659 #else |
|
1660 COpenFontSessionCacheEntry* e = iEntry[index]; |
|
1661 #endif //FNTSTORE_SUPPORT_FMM |
|
1662 if (!e) |
|
1663 { |
|
1664 if (aIndex == -1) |
|
1665 aIndex = index; |
|
1666 } |
|
1667 else |
|
1668 { |
|
1669 #ifdef FNTSTORE_SUPPORT_FMM |
|
1670 if (e->Font() == aFont && e->iCode == aCode) |
|
1671 #else |
|
1672 if (e->iFont == aFont && e->iCode == aCode) |
|
1673 #endif //FNTSTORE_SUPPORT_FMM |
|
1674 { |
|
1675 e->iLastAccess = iLastAccess++; |
|
1676 return e; |
|
1677 } |
|
1678 if (e->iLastAccess < oldest) |
|
1679 { |
|
1680 oldest = e->iLastAccess; |
|
1681 oldest_index = index; |
|
1682 } |
|
1683 } |
|
1684 } |
|
1685 if (aIndex == -1) |
|
1686 aIndex = oldest_index; |
|
1687 return NULL; |
|
1688 } |
|
1689 |
|
1690 |
|
1691 void COpenFontSessionCache::Insert(RHeap* aHeap, COpenFontSessionCacheEntry* aEntry, TInt aIndex) |
|
1692 { |
|
1693 if ((aIndex < 0) || (aIndex > iEntries)) |
|
1694 Panic(EFntSessionCacheIndexOutOfRange); |
|
1695 #ifdef FNTSTORE_SUPPORT_FMM |
|
1696 COpenFontSessionCacheEntry* e = ToCOpenFontSessionCacheEntryPointer(Entry()[aIndex]); |
|
1697 COpenFontGlyph::Delete(aHeap, e); |
|
1698 Entry()[aIndex] = reinterpret_cast<TInt>(aEntry) - reinterpret_cast<TInt>(this); |
|
1699 #else |
|
1700 COpenFontGlyph::Delete(aHeap, iEntry[aIndex]); |
|
1701 iEntry[aIndex] = aEntry; |
|
1702 #endif //FNTSTORE_SUPPORT_FMM |
|
1703 aEntry->iLastAccess = iLastAccess++; |
|
1704 } |
|
1705 |
|
1706 COpenFontSessionCache::COpenFontSessionCache(TInt aSessionHandle, TInt aEntries) |
|
1707 : iSessionHandle(aSessionHandle), |
|
1708 iEntries(aEntries), |
|
1709 iLastAccess(0), |
|
1710 #ifdef FNTSTORE_SUPPORT_FMM |
|
1711 iEntryOffset(0) |
|
1712 #else |
|
1713 iEntry(NULL) |
|
1714 #endif //FNTSTORE_SUPPORT_FMM |
|
1715 { |
|
1716 } |
|
1717 |
|
1718 #ifdef FNTSTORE_SUPPORT_FMM |
|
1719 |
|
1720 inline TInt* COpenFontSessionCache::Entry() const |
|
1721 { |
|
1722 if (iEntryOffset) |
|
1723 { |
|
1724 return reinterpret_cast<TInt*>(reinterpret_cast<TInt>(this) + iEntryOffset); |
|
1725 } |
|
1726 return NULL; |
|
1727 } |
|
1728 |
|
1729 inline COpenFontSessionCacheEntry* COpenFontSessionCache::ToCOpenFontSessionCacheEntryPointer(TInt aOffset)const |
|
1730 { |
|
1731 if(aOffset) |
|
1732 { |
|
1733 return reinterpret_cast<COpenFontSessionCacheEntry*>(reinterpret_cast<TInt>(this) + aOffset); |
|
1734 } |
|
1735 return NULL; |
|
1736 } |
|
1737 |
|
1738 #endif // FNTSTORE_SUPPORT_FMM |
|
1739 |
1364 |
1740 /*COpenFontSessionCacheListItem*/ |
1365 /*COpenFontSessionCacheListItem*/ |
1741 #ifdef FNTSTORE_SUPPORT_FMM |
|
1742 COpenFontSessionCacheListItem::COpenFontSessionCacheListItem(COpenFontSessionCache* aCache): |
1366 COpenFontSessionCacheListItem::COpenFontSessionCacheListItem(COpenFontSessionCache* aCache): |
1743 iNextOffset(NULL) |
1367 iNextOffset(NULL) |
1744 { |
1368 { |
1745 if(aCache) |
1369 if(aCache != NULL) |
1746 { |
1370 { |
1747 iCacheOffset = (TInt)aCache - (TInt)this; |
1371 iCacheOffset = reinterpret_cast<TInt>(aCache) - reinterpret_cast<TInt>(this); |
1748 } |
1372 } |
1749 else |
1373 else |
1750 { |
1374 { |
1751 iCacheOffset = NULL; |
1375 iCacheOffset = NULL; |
1752 } |
1376 } |
1753 } |
1377 } |
1754 |
1378 |
1755 COpenFontSessionCacheListItem::~COpenFontSessionCacheListItem() |
1379 COpenFontSessionCacheListItem::~COpenFontSessionCacheListItem() |
1756 { |
1380 { |
1757 } |
1381 } |
1758 #endif // FNTSTORE_SUPPORT_FMM |
|
1759 |
1382 |
1760 /** Delete a COpenFontSessionCacheListItem from the passed heap. |
1383 /** Delete a COpenFontSessionCacheListItem from the passed heap. |
1761 |
1384 |
1762 @param aHeap The heap to delete the COpenFontSessionCacheListItem from. |
1385 @param aHeap The heap to delete the COpenFontSessionCacheListItem from. |
1763 */ |
1386 */ |
1764 void COpenFontSessionCacheListItem::Delete(RHeap* aHeap) |
1387 void COpenFontSessionCacheListItem::Delete(RHeap* aHeap) |
1765 { |
1388 { |
1766 #ifdef FNTSTORE_SUPPORT_FMM |
1389 COpenFontSessionCache* cache = Cache(); |
1767 Cache()->Delete(aHeap); |
1390 if (cache != NULL) |
1768 aHeap->Free(Cache()); |
1391 { |
1769 iCacheOffset=NULL; |
1392 cache->Delete(aHeap); |
1770 iNextOffset=NULL; |
1393 aHeap->Free(cache); |
1771 #else |
1394 } |
1772 iCache->Delete(aHeap); |
1395 iCacheOffset=NULL; |
1773 aHeap->Free(iCache); |
1396 iNextOffset=NULL; |
1774 iCache=NULL; |
|
1775 #endif // FNTSTORE_SUPPORT_FMM |
|
1776 } |
1397 } |
1777 |
1398 |
1778 #ifdef FNTSTORE_SUPPORT_FMM |
|
1779 /** Get the next item to this cache list item. |
1399 /** Get the next item to this cache list item. |
1780 |
1400 |
1781 @return A pointer to the next item to this one in the session cache, or NULL |
1401 @return A pointer to the next item to this one in the session cache, or NULL |
1782 if there is no next item. |
1402 if there is no next item. |
1783 */ |
1403 */ |
1784 COpenFontSessionCacheListItem* COpenFontSessionCacheListItem::Next() |
1404 COpenFontSessionCacheListItem* COpenFontSessionCacheListItem::Next() |
1785 { |
1405 { |
1786 if(iNextOffset) |
1406 if(iNextOffset) |
1787 { |
1407 { |
1788 COpenFontSessionCacheListItem* next = (COpenFontSessionCacheListItem*)((TInt)this + (TInt)iNextOffset); |
1408 COpenFontSessionCacheListItem* next = reinterpret_cast<COpenFontSessionCacheListItem*>(reinterpret_cast<TInt>(this) + iNextOffset); |
1789 return next; |
1409 return next; |
1790 } |
1410 } |
1791 else |
1411 else |
1792 { |
1412 { |
1793 return NULL; |
1413 return NULL; |