update to latest api (need a test for this port!)



git-svn-id: http://skia.googlecode.com/svn/trunk@225 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/ports/SkFontHost_win.cpp b/src/ports/SkFontHost_win.cpp
index 4cc04b5..a081c63 100644
--- a/src/ports/SkFontHost_win.cpp
+++ b/src/ports/SkFontHost_win.cpp
@@ -1,16 +1,16 @@
 /*

  ** Copyright 2006, The Android Open Source Project

  **

- ** Licensed under the Apache License, Version 2.0 (the "License"); 

- ** you may not use this file except in compliance with the License. 

- ** You may obtain a copy of the License at 

+ ** Licensed under the Apache License, Version 2.0 (the "License");

+ ** you may not use this file except in compliance with the License.

+ ** You may obtain a copy of the License at

  **

- **     http://www.apache.org/licenses/LICENSE-2.0 

+ **     http://www.apache.org/licenses/LICENSE-2.0

  **

- ** Unless required by applicable law or agreed to in writing, software 

- ** distributed under the License is distributed on an "AS IS" BASIS, 

- ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 

- ** See the License for the specific language governing permissions and 

+ ** Unless required by applicable law or agreed to in writing, software

+ ** distributed under the License is distributed on an "AS IS" BASIS,

+ ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

+ ** See the License for the specific language governing permissions and

  ** limitations under the License.

  */

 

@@ -34,7 +34,7 @@
 static LOGFONT gDefaultFont = {0};

 

 static const uint16_t BUFFERSIZE = (16384 - 32);

-static uint8_t glyphbuf[BUFFERSIZE]; 

+static uint8_t glyphbuf[BUFFERSIZE];

 

 // Give 1MB font cache budget

 #define FONT_CACHE_MEMORY_BUDGET    (1024 * 1024)

@@ -52,32 +52,32 @@
 uint32_t FontFaceChecksum(const TCHAR *q, SkTypeface::Style style)

 {

     if (!q) return style;

-    

+

     // From "Performance in Practice of String Hashing Functions"

     // Ramakrishna & Zobel

     const uint32_t L = 5;

     const uint32_t R = 2;

-    

+

     uint32_t h = 0x12345678;

     while (*q) {

         //uint32_t ql = tolower(*q);

         h ^= ((h << L) + (h >> R) + *q);

         q ++;

     }

-    

+

     // add style

     h = _rotl(h, 3) ^ style;

-    

+

     return h;

 }

 

-static SkTypeface::Style GetFontStyle(const LOGFONT& lf) {         

+static SkTypeface::Style GetFontStyle(const LOGFONT& lf) {

     int style = SkTypeface::kNormal;

     if (lf.lfWeight == FW_SEMIBOLD || lf.lfWeight == FW_DEMIBOLD || lf.lfWeight == FW_BOLD)

         style |= SkTypeface::kBold;

     if (lf.lfItalic)

         style |= SkTypeface::kItalic;

-    

+

     return (SkTypeface::Style)style;

 }

 

@@ -86,12 +86,12 @@
     uint32_t        fRefCnt;

     uint32_t        fFontID;    // checksum of fFace

     LOGFONT         fFace;

-    

-    SkFaceRec() : fFontID(-1), fRefCnt(0) { 

+

+    SkFaceRec() : fFontID(-1), fRefCnt(0) {

         memset(&fFace, 0, sizeof(LOGFONT));

     }

     ~SkFaceRec() {}

-    

+

     uint32_t ref() {

         return ++fRefCnt;

     }

@@ -108,7 +108,7 @@
         }

         rec = rec->fNext;

     }

-    

+

     return NULL;

 }

 

@@ -119,18 +119,18 @@
     if (rec) {

         return rec;  // found?

     }

-    

+

     rec = SkNEW(SkFaceRec);

     rec->fFontID = id;

     memcpy(&(rec->fFace), &lf, sizeof(LOGFONT));

     rec->fNext = gFaceRecHead;

     gFaceRecHead = rec;

-    

+

     return rec;

 }

 

 static void unref_ft_face(uint32_t fontID) {

-    

+

     SkFaceRec* rec = gFaceRecHead;

     SkFaceRec* prev = NULL;

     while (rec) {

@@ -141,7 +141,7 @@
                     prev->fNext = next;

                 else

                     gFaceRecHead = next;

-                

+

                 SkDELETE(rec);

             }

             return;

@@ -155,50 +155,57 @@
 // have to do this because SkTypeface::SkTypeface() is protected

 class FontFaceRec_Typeface : public SkTypeface {

 public:

-    

+

     FontFaceRec_Typeface(Style style, uint32_t id) : SkTypeface(style, id) {};

-    

+

     virtual ~FontFaceRec_Typeface() {};

 };

 

 static const LOGFONT* get_default_font() {

     // don't hardcode on Windows, Win2000, XP, Vista, and international all have different default

     // and the user could change too

-    

+

     if (gDefaultFont.lfFaceName[0] != 0) {

         return &gDefaultFont;

     }

-    

+

     NONCLIENTMETRICS ncm;

     ncm.cbSize = sizeof(NONCLIENTMETRICS);

     SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(ncm), &ncm, 0);

-    

+

     memcpy(&gDefaultFont, &(ncm.lfMessageFont), sizeof(LOGFONT));

-    

+

     return &gDefaultFont;

 }

 

 static SkTypeface* CreateTypeface_(const LOGFONT& lf) {

-    

+

     SkTypeface::Style style = GetFontStyle(lf);

     FontFaceRec_Typeface* ptypeface = new FontFaceRec_Typeface(style, FontFaceChecksum(lf.lfFaceName, style));

-    

+

     if (NULL == ptypeface) {

         SkASSERT(false);

         return NULL;

     }

-    

+

     SkFaceRec* rec = insert_ft_face(lf);

     SkASSERT(rec);

-    

+

     return ptypeface;

 }

 

+uint32_t SkFontHost::NextLogicalFont(uint32_t fontID) {

+  // Zero means that we don't have any fallback fonts for this fontID.

+  // This function is implemented on Android, but doesn't have much

+  // meaning here.

+  return 0;

+}

+

 class SkScalerContext_Windows : public SkScalerContext {

 public:

     SkScalerContext_Windows(const SkDescriptor* desc);

     virtual ~SkScalerContext_Windows();

-    

+

 protected:

     virtual unsigned generateGlyphCount() const;

     virtual uint16_t generateCharToGlyph(SkUnichar uni);

@@ -211,7 +218,7 @@
     //virtual SkDeviceContext getDC() {return ddc;}

 private:

     uint32_t    fFontID;

-    LOGFONT     lf;              

+    LOGFONT     lf;

     MAT2        mat22;

     HDC         ddc;

     HFONT       savefont;

@@ -220,7 +227,7 @@
 

 SkScalerContext_Windows::SkScalerContext_Windows(const SkDescriptor* desc) : SkScalerContext(desc), ddc(0), font(0), savefont(0) {

     SkAutoMutexAcquire  ac(gFTMutex);

-    

+

     fFontID = fRec.fFontID;

     SkFaceRec* rec = find_ft_face(fRec.fFontID);

     if (rec) {

@@ -231,23 +238,25 @@
         SkASSERT(false);

         memcpy(&lf, &gDefaultFont, sizeof(LOGFONT));

     }

-    

-    mat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]);    

-    mat22.eM12 = SkScalarToFIXED(-fRec.fPost2x2[0][1]);

-    mat22.eM21 = SkScalarToFIXED(fRec.fPost2x2[1][0]);

+

+    mat22.eM11 = SkScalarToFIXED(fRec.fPost2x2[0][0]);

+    mat22.eM12 = SkScalarToFIXED(fRec.fPost2x2[0][1]);

+    mat22.eM21 = SkScalarToFIXED(-fRec.fPost2x2[1][0]);

     mat22.eM22 = SkScalarToFIXED(-fRec.fPost2x2[1][1]);

-    

+

     ddc = ::CreateCompatibleDC(NULL);

     SetBkMode(ddc, TRANSPARENT);

-    

-    lf.lfHeight = SkScalarFloor(fRec.fTextSize);

+

+    // Perform the dpi adjustment.

+    LONG lfHeight = -(fRec.fTextSize * GetDeviceCaps(ddc, LOGPIXELSY) / 72);

+    lf.lfHeight = lfHeight;

     font = CreateFontIndirect(&lf);

     savefont = (HFONT)SelectObject(ddc, font);

 }

 

 SkScalerContext_Windows::~SkScalerContext_Windows() {

     unref_ft_face(fFontID);

-    

+

     if (ddc) {

         ::SelectObject(ddc, savefont);

         ::DeleteDC(ddc);

@@ -264,11 +273,11 @@
 }

 

 uint16_t SkScalerContext_Windows::generateCharToGlyph(SkUnichar uni) {

-    

+

     //uint16_t index = 0;

     //GetGlyphIndicesW(ddc, &(uint16_t&)uni, 1, &index, 0);

     //return index;

-    

+

     // let's just use the uni as index on Windows

     return SkToU16(uni);

 }

@@ -278,21 +287,21 @@
 }

 

 void SkScalerContext_Windows::generateMetrics(SkGlyph* glyph) {

-    

+

     SkASSERT(ddc);

-    

+

     GLYPHMETRICS gm;

     memset(&gm, 0, sizeof(gm));

-    

+

     glyph->fRsbDelta = 0;

     glyph->fLsbDelta = 0;

-    

+

     UINT glyphIndexFlag = 0; //glyph->fIsCodePoint ? 0 : GGO_GLYPH_INDEX;

     //    UINT glyphIndexFlag = GGO_GLYPH_INDEX;

     // Note: need to use GGO_GRAY8_BITMAP instead of GGO_METRICS because GGO_METRICS returns a smaller

     // BlackBlox; we need the bigger one in case we need the image.  fAdvance is the same.

     uint32_t ret = GetGlyphOutlineW(ddc, glyph->getGlyphID(0), GGO_GRAY8_BITMAP | glyphIndexFlag, &gm, 0, NULL, &mat22);

-    

+

     if (GDI_ERROR != ret) {

         if (ret == 0) {

             // for white space, ret is zero and gmBlackBoxX, gmBlackBoxY are 1 incorrectly!

@@ -307,7 +316,7 @@
     } else {

         glyph->fWidth = 0;

     }

-    

+

 #if 0

     char buf[1024];

     sprintf(buf, "generateMetrics: id:%d, w=%d, h=%d, font:%s, fh:%d\n", glyph->fID, glyph->fWidth, glyph->fHeight, lf.lfFaceName, lf.lfHeight);

@@ -316,29 +325,54 @@
 }

 

 void SkScalerContext_Windows::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my) {

-    //SkASSERT(false);

-    if (mx)

-        memset(mx, 0, sizeof(SkPaint::FontMetrics));

-    if (my)

-        memset(my, 0, sizeof(SkPaint::FontMetrics));

-    return;

+// Note: This code was borrowed from generateLineHeight, which has a note

+// stating that it may be incorrect.

+    if (!(mx || my))

+      return;

+

+    SkASSERT(ddc);

+

+    OUTLINETEXTMETRIC otm;

+

+    uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm);

+    if (sizeof(otm) != ret) {

+      return;

+    }

+

+    if (mx) {

+      mx->fTop = -SkIntToScalar(otm.otmTextMetrics.tmAscent);  // Actually a long.

+      mx->fAscent = -SkIntToScalar(otm.otmAscent);

+      mx->fDescent = -SkIntToScalar(otm.otmDescent);

+      mx->fBottom = SkIntToScalar(otm.otmTextMetrics.tmDescent);  // Long

+      mx->fLeading = SkIntToScalar(otm.otmTextMetrics.tmInternalLeading

+          + otm.otmTextMetrics.tmExternalLeading);  // Long

+    }

+

+    if (my) {

+      my->fTop = -SkIntToScalar(otm.otmTextMetrics.tmAscent);  // Actually a long.

+      my->fAscent = -SkIntToScalar(otm.otmAscent);

+      my->fDescent = -SkIntToScalar(otm.otmDescent);

+      my->fBottom = SkIntToScalar(otm.otmTextMetrics.tmDescent);  // Long

+      my->fLeading = SkIntToScalar(otm.otmTextMetrics.tmInternalLeading

+          + otm.otmTextMetrics.tmExternalLeading);  // Long

+    }

 }

 

 void SkScalerContext_Windows::generateImage(const SkGlyph& glyph) {

-    

+

     SkAutoMutexAcquire  ac(gFTMutex);

-    

+

     SkASSERT(ddc);

-    

+

     GLYPHMETRICS gm;

     memset(&gm, 0, sizeof(gm));

-    

+

 #if 0

     char buf[1024];

     sprintf(buf, "generateImage: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);

     OutputDebugString(buf);

 #endif

-    

+

     uint32_t bytecount = 0;

     UINT glyphIndexFlag = 0; //glyph.fIsCodePoint ? 0 : GGO_GLYPH_INDEX;

     //    UINT glyphIndexFlag = GGO_GLYPH_INDEX;

@@ -347,21 +381,21 @@
         uint8_t *pBuff = new uint8_t[total_size];

         if (NULL != pBuff) {

             total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_GRAY8_BITMAP | glyphIndexFlag, &gm, total_size, pBuff, &mat22);

-            

+

             SkASSERT(total_size != GDI_ERROR);

-            

+

             SkASSERT(glyph.fWidth == gm.gmBlackBoxX);

             SkASSERT(glyph.fHeight == gm.gmBlackBoxY);

-            

+

             uint8_t* dst = (uint8_t*)glyph.fImage;

             uint32_t pitch = (gm.gmBlackBoxX + 3) & ~0x3;

             if (pitch != glyph.rowBytes()) {

                 SkASSERT(false); // glyph.fImage has different rowsize!?

             }

-            

+

             for (int32_t y = gm.gmBlackBoxY - 1; y >= 0; y--) {

                 uint8_t* src = pBuff + pitch * y;

-                

+

                 for (uint32_t x = 0; x < gm.gmBlackBoxX; x++) {

                     if (*src > 63) {

                         *dst = 0xFF;

@@ -376,66 +410,66 @@
                 memset(dst, 0, glyph.rowBytes() - glyph.fWidth);

                 dst += glyph.rowBytes() - glyph.fWidth;

             }

-            

+

             delete[] pBuff;

         }

     }

-    

+

     SkASSERT(GDI_ERROR != total_size && total_size >= 0);

-    

+

 }

 

 void SkScalerContext_Windows::generatePath(const SkGlyph& glyph, SkPath* path) {

-    

+

     SkAutoMutexAcquire  ac(gFTMutex);

-    

+

     SkASSERT(&glyph && path);

     SkASSERT(ddc);

-    

+

     path->reset();

-    

+

 #if 0

     char buf[1024];

     sprintf(buf, "generatePath: id:%d, w=%d, h=%d, font:%s,fh:%d\n", glyph.fID, glyph.fWidth, glyph.fHeight, lf.lfFaceName, lf.lfHeight);

     OutputDebugString(buf);

 #endif

-    

+

     GLYPHMETRICS gm;

     UINT glyphIndexFlag = 0; //glyph.fIsCodePoint ? 0 : GGO_GLYPH_INDEX;

     uint32_t total_size = GetGlyphOutlineW(ddc, glyph.fID, GGO_NATIVE | glyphIndexFlag, &gm, BUFFERSIZE, glyphbuf, &mat22);

-    

+

     if (GDI_ERROR != total_size) {

-        

+

         const uint8_t* cur_glyph = glyphbuf;

         const uint8_t* end_glyph = glyphbuf + total_size;

-        

+

         while(cur_glyph < end_glyph) {

             const TTPOLYGONHEADER* th = (TTPOLYGONHEADER*)cur_glyph;

-            

+

             const uint8_t* end_poly = cur_glyph + th->cb;

             const uint8_t* cur_poly = cur_glyph + sizeof(TTPOLYGONHEADER);

-            

+

             path->moveTo(SkFixedToScalar(*(SkFixed*)(&th->pfxStart.x)), SkFixedToScalar(*(SkFixed*)(&th->pfxStart.y)));

-            

+

             while(cur_poly < end_poly) {

                 const TTPOLYCURVE* pc = (const TTPOLYCURVE*)cur_poly;

-                

+

                 if (pc->wType == TT_PRIM_LINE) {

                     for (uint16_t i = 0; i < pc->cpfx; i++) {

                         path->lineTo(SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].x)), SkFixedToScalar(*(SkFixed*)(&pc->apfx[i].y)));

                     }

                 }

-                

+

                 if (pc->wType == TT_PRIM_QSPLINE) {

                     for (uint16_t u = 0; u < pc->cpfx - 1; u++) { // Walk through points in spline

                         POINTFX pnt_b = pc->apfx[u];    // B is always the current point

                         POINTFX pnt_c = pc->apfx[u+1];

-                        

-                        if (u < pc->cpfx - 2) {          // If not on last spline, compute C                            

+

+                        if (u < pc->cpfx - 2) {          // If not on last spline, compute C

                             pnt_c.x = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.x), *(SkFixed*)(&pnt_c.x)));

                             pnt_c.y = SkFixedToFIXED(SkFixedAve(*(SkFixed*)(&pnt_b.y), *(SkFixed*)(&pnt_c.y)));

                         }

-                        

+

                         path->quadTo(SkFixedToScalar(*(SkFixed*)(&pnt_b.x)), SkFixedToScalar(*(SkFixed*)(&pnt_b.y)), SkFixedToScalar(*(SkFixed*)(&pnt_c.x)), SkFixedToScalar(*(SkFixed*)(&pnt_c.y)));

                     }

                 }

@@ -456,20 +490,20 @@
 

 // Note:  not sure this is the correct implementation

 void SkScalerContext_Windows::generateLineHeight(SkPoint* ascent, SkPoint* descent) {

-    

+

     SkASSERT(ddc);

-    

+

     OUTLINETEXTMETRIC otm;

-    

+

     uint32_t ret = GetOutlineTextMetrics(ddc, sizeof(otm), &otm);

-    

+

     if (sizeof(otm) == ret) {

         if (ascent)

             ascent->iset(0, otm.otmAscent);

         if (descent)

             descent->iset(0, otm.otmDescent);

     }

-    

+

     return;

 }

 

@@ -483,7 +517,7 @@
 }

 

 SkTypeface* SkFontHost::CreateTypefaceFromStream(SkStream* stream) {

-    

+

     //Should not be used on Windows, keep linker happy

     SkASSERT(false);

     get_default_font();

@@ -494,24 +528,6 @@
     return SkNEW_ARGS(SkScalerContext_Windows, (desc));

 }

 

-SkScalerContext* SkFontHost::CreateFallbackScalerContext(const SkScalerContext::Rec& rec) {

-    get_default_font();

-    

-    SkAutoDescriptor    ad(sizeof(rec) + sizeof(gDefaultFont) + SkDescriptor::ComputeOverhead(2));

-    SkDescriptor*       desc = ad.getDesc();

-    

-    desc->init();

-    SkScalerContext::Rec* newRec =

-    (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);

-    

-    get_default_font();

-    CreateTypeface_(gDefaultFont);

-    newRec->fFontID = FontFaceChecksum(gDefaultFont.lfFaceName, GetFontStyle(gDefaultFont));

-    desc->computeChecksum();

-    

-    return SkFontHost::CreateScalerContext(desc);

-}

-

 /** Return the closest matching typeface given either an existing family

  (specified by a typeface in that family) or by a familyName, and a

  requested style.

@@ -522,8 +538,9 @@
  */

 

 SkTypeface* SkFontHost::CreateTypeface(const SkTypeface* familyFace,

-                            const char familyName[], SkTypeface::Style style) {

-    

+                                       const char familyName[],

+                                       SkTypeface::Style style) {

+

     SkAutoMutexAcquire  ac(gFTMutex);

 

 #ifndef CAN_USE_LOGFONT_NAME

@@ -533,13 +550,13 @@
 

     // clip to legal style bits

     style = (SkTypeface::Style)(style & SkTypeface::kBoldItalic);

-    

+

     SkTypeface* tf = NULL;

     if (NULL == familyFace && NULL == familyName) {

         LOGFONT lf;

         get_default_font();

         memcpy(&lf, &gDefaultFont, sizeof(LOGFONT));

-        lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ; 

+        lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;

         lf.lfItalic = ((style & SkTypeface::kItalic) != 0);

         tf = CreateTypeface_(lf);

     } else {

@@ -559,17 +576,31 @@
         }

         else {

             memset(&lf, 0, sizeof(LOGFONT));

-            

+

             lf.lfHeight = -11; // default

             lf.lfQuality = PROOF_QUALITY;

             lf.lfCharSet = DEFAULT_CHARSET;

-            

-            _tcsncpy(lf.lfFaceName, familyName, LF_FACESIZE);

+

+#ifdef UNICODE

+            // Get the buffer size needed first.

+            size_t str_len = ::MultiByteToWideChar(CP_UTF8, 0, familyName,

+                                                   -1, NULL, 0);

+            // Allocate a buffer (str_len already has terminating null

+            // accounted for).

+            wchar_t *wideFamilyName = new wchar_t[str_len];

+            // Now actually convert the string.

+            ::MultiByteToWideChar(CP_UTF8, 0, familyName, -1,

+                                  wideFamilyName, str_len);

+            ::wcsncpy(lf.lfFaceName, wideFamilyName, LF_FACESIZE);

+            delete [] wideFamilyName;

+#else

+            ::strncpy(lf.lfFaceName, familyName, LF_FACESIZE);

+#endif

             lf.lfFaceName[LF_FACESIZE-1] = '\0';

         }

-        

+

         // use the style desired

-        lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ; 

+        lf.lfWeight = (style & SkTypeface::kBold) != 0 ? FW_BOLD : FW_NORMAL ;

         lf.lfItalic = ((style & SkTypeface::kItalic) != 0);

         tf = CreateTypeface_(lf);

 #endif

@@ -598,5 +629,9 @@
     tables[1] = NULL;   // white gamma (e.g. exp= 1/1.4)

 }

 

-#endif // WIN32

+SkTypeface* SkFontHost::CreateTypefaceFromFile(const char path[]) {

+    SkASSERT(!"SkFontHost::CreateTypefaceFromFile unimplemented");

+    return NULL;

+}

 

+#endif // WIN32