のねのBlog

パソコンの問題や、ソフトウェアの開発で起きた問題など書いていきます。よろしくお願いします^^。

lookupMetrics

    236 SkGlyph* SkGlyphCache::lookupMetrics(uint32_t id, MetricsType mtype) {
    237     SkGlyph* glyph;
    238 
    239     int     hi = 0;
    240     int     count = fGlyphArray.count();
    241 
    242     if (count) {
    243         SkGlyph**   gptr = fGlyphArray.begin();
    244         int     lo = 0;
    245 
    246         hi = count - 1;
    247         while (lo < hi) {
    248             int mid = (hi + lo) >> 1;
    249             if (gptr[mid]->fID < id) {
    250                 lo = mid + 1;
    251             } else {
    252                 hi = mid;
    253             }
    254         }
    255         glyph = gptr[hi];
    256         if (glyph->fID == id) {
    257             if (kFull_MetricsType == mtype && glyph->isJustAdvance()) {
    258                 fScalerContext->getMetrics(glyph);
    259             }
    260             return glyph;
    261         }
    262 
    263         // check if we need to bump hi before falling though to the allocator
    264         if (glyph->fID < id) {
    265             hi += 1;
    266         }
    267     }
    268 
    269     // not found, but hi tells us where to inser the new glyph
    270     fMemoryUsed += sizeof(SkGlyph);
    271 
    272     glyph = (SkGlyph*)fGlyphAlloc.alloc(sizeof(SkGlyph),
    273                                         SkChunkAlloc::kThrow_AllocFailType);
    274     glyph->init(id);
    275     *fGlyphArray.insert(hi) = glyph;
    276 
    277     if (kJustAdvance_MetricsType == mtype) {
    278         fScalerContext->getAdvance(glyph);
    279         fAdvanceCount += 1;
    280     } else {
    281         SkASSERT(kFull_MetricsType == mtype);
    282         fScalerContext->getMetrics(glyph); <=====
    283         fMetricsCount += 1;
    284     }
    285 
    286     return glyph;
    287 }

    202     enum MetricsType {
    203         kJustAdvance_MetricsType, <=== 0?
    204         kFull_MetricsType         <=== 1?
    205     };
    271 void SkScalerContext::getMetrics(SkGlyph* glyph) {
    272     this->getGlyphContext(*glyph)->generateMetrics(glyph); <=========
    273 
    274     // for now we have separate cache entries for devkerning on and off
    275     // in the future we might share caches, but make our measure/draw
    276     // code make the distinction. Thus we zap the values if the caller
    277     // has not asked for them.
    278     if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
    279         // no devkern, so zap the fields
    280         glyph->fLsbDelta = glyph->fRsbDelta = 0;
    281     }
    282 
    283     // if either dimension is empty, zap the image bounds of the glyph
    284     if (0 == glyph->fWidth || 0 == glyph->fHeight) {
    285         glyph->fWidth   = 0;
    286         glyph->fHeight  = 0;
    287         glyph->fTop     = 0;
    288         glyph->fLeft    = 0;
    289         glyph->fMaskFormat = 0;
    290         return;
    291     }
    292 
    293     if (fGenerateImageFromPath) {
    294         SkPath      devPath, fillPath;
    295         SkMatrix    fillToDevMatrix;
    296 
    297         this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
    298 
    299         if (fRasterizer) {
    300             SkMask  mask;
    301 
    302             if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
    303                                        fMaskFilter, &mask,
    304                                        SkMask::kJustComputeBounds_CreateMode)) {
    305                 glyph->fLeft    = mask.fBounds.fLeft;
    306                 glyph->fTop     = mask.fBounds.fTop;
    307                 glyph->fWidth   = SkToU16(mask.fBounds.width());
    308                 glyph->fHeight  = SkToU16(mask.fBounds.height());
    309             } else {
    310                 goto SK_ERROR;
    311             }
    312         } else {
    313             // just use devPath
    314             SkIRect ir;
    315             devPath.getBounds().roundOut(&ir);
    316 
    317             if (ir.isEmpty() || !ir.is16Bit()) {
    318                 goto SK_ERROR;
    319             }
    320             glyph->fLeft    = ir.fLeft;
    321             glyph->fTop     = ir.fTop;
    322             glyph->fWidth   = SkToU16(ir.width());
    323             glyph->fHeight  = SkToU16(ir.height());
    324         }
    325     }
    326 
    327 	if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
    328 		glyph->fMaskFormat = fRec.fMaskFormat;
    329 	}
    330 
    331     if (fMaskFilter) {
    332         SkMask      src, dst;
    333         SkMatrix    matrix;
    334 
    335         glyph->toMask(&src);
    336         fRec.getMatrixFrom2x2(&matrix);
    337 
    338         src.fImage = NULL;  // only want the bounds from the filter
    339         if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) {
    340             SkASSERT(dst.fImage == NULL);
    341             glyph->fLeft    = dst.fBounds.fLeft;
    342             glyph->fTop     = dst.fBounds.fTop;
    343             glyph->fWidth   = SkToU16(dst.fBounds.width());
    344             glyph->fHeight  = SkToU16(dst.fBounds.height());
    345             glyph->fMaskFormat = dst.fFormat;
    346         }
    347     }
    348     return;
    349 
    350 SK_ERROR:
    351     // draw nothing 'cause we failed
    352     glyph->fLeft    = 0;
    353     glyph->fTop     = 0;
    354     glyph->fWidth   = 0;
    355     glyph->fHeight  = 0;
    356     // put a valid value here, in case it was earlier set to
    357     // MASK_FORMAT_JUST_ADVANCE
    358     glyph->fMaskFormat = fRec.fMaskFormat;
    359 }
 1036 void SkScalerContext_FreeType::generateMetrics(SkGlyph* glyph) {
   1037     SkAutoMutexAcquire  ac(gFTMutex);
   1038 
   1039     glyph->fRsbDelta = 0;
   1040     glyph->fLsbDelta = 0;
   1041 
   1042     FT_Error    err;
   1043 
   1044     if (this->setupSize()) {
   1045         goto ERROR;
   1046     }
   1047 
   1048     err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags );
   1049     if (err != 0) {
   1050         SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n",
   1051                     fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, err));
   1052     ERROR:
   1053         glyph->zeroMetrics();
   1054         return;
   1055     }
   1056 
   1057     SkFixed vLeft, vTop;
   1058 
   1059     switch ( fFace->glyph->format ) {
   1060       case FT_GLYPH_FORMAT_OUTLINE: {
   1061         FT_BBox bbox;
   1062 
   1063         if (0 == fFace->glyph->outline.n_contours) {
   1064             glyph->fWidth = 0;
   1065             glyph->fHeight = 0;
   1066             glyph->fTop = 0;
   1067             glyph->fLeft = 0;
   1068             break;
   1069         }
   1070 
   1071         if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) {
   1072             emboldenOutline(&fFace->glyph->outline);
   1073         }
   1074 
   1075         getBBoxForCurrentGlyph(glyph, &bbox, true);
   1076 
   1077         glyph->fWidth   = SkToU16((bbox.xMax - bbox.xMin) >> 6);
   1078         glyph->fHeight  = SkToU16((bbox.yMax - bbox.yMin) >> 6);
   1079         glyph->fTop     = -SkToS16(bbox.yMax >> 6);
   1080         glyph->fLeft    = SkToS16(bbox.xMin >> 6);
   1081 
   1082         if ((fRec.fFlags & SkScalerContext::kVertical_Flag)) {
   1083             vLeft = Dot6ToFixed(bbox.xMin);
   1084             vTop = Dot6ToFixed(bbox.yMax);
   1085         }
   1086 
   1087         updateGlyphIfLCD(glyph);
   1088 
   1089         break;
   1090       }
   1091 
   1092       case FT_GLYPH_FORMAT_BITMAP:
   1093         if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) {
   1094             FT_GlyphSlot_Own_Bitmap(fFace->glyph);
   1095             FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmboldenStrength, 0);
   1096         }
   1097 
   1098         if (fUseVertMetrics) {
   1099             FT_Vector vector;
   1100             vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.horiBearingX;
   1101             vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.horiBearingY;
   1102             FT_Vector_Transform(&vector, &fMatrix22);
   1103             fFace->glyph->bitmap_left += SkFDot6Floor(vector.x);
   1104             fFace->glyph->bitmap_top  += SkFDot6Floor(vector.y);
   1105         }
   1106 
   1107         glyph->fWidth   = SkToU16(fFace->glyph->bitmap.width);
   1108         glyph->fHeight  = SkToU16(fFace->glyph->bitmap.rows);
   1109         glyph->fTop     = -SkToS16(fFace->glyph->bitmap_top);
   1110         glyph->fLeft    = SkToS16(fFace->glyph->bitmap_left);
   1111         break;
   1112 
   1113       default:
   1114         SkDEBUGFAIL("unknown glyph format");
   1115         goto ERROR;
   1116     }
   1117 
   1118     if ((fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) == 0) {
   1119         glyph->fAdvanceX = SkFDot6ToFixed(fFace->glyph->advance.x);
   1120         glyph->fAdvanceY = -SkFDot6ToFixed(fFace->glyph->advance.y);
   1121         if (fRec.fFlags & kDevKernText_Flag) {
   1122             glyph->fRsbDelta = SkToS8(fFace->glyph->rsb_delta);
   1123             glyph->fLsbDelta = SkToS8(fFace->glyph->lsb_delta);
   1124         }
   1125     } else {
   1126         glyph->fAdvanceX = SkFixedMul(fMatrix22.xx, fFace->glyph->linearHoriAdvance);
   1127         glyph->fAdvanceY = -SkFixedMul(fMatrix22.yx, fFace->glyph->linearHoriAdvance);
   1128     }
   1129 
   1130     if (fUseVertMetrics) {
   1131         if (fDoLinearMetrics) {
   1132             glyph->fAdvanceX = -SkFixedMul(fMatrix22.xy, fFace->glyph->linearVertAdvance);
   1133             glyph->fAdvanceY = SkFixedMul(fMatrix22.yy, fFace->glyph->linearVertAdvance);
   1134         } else {
   1135             glyph->fAdvanceX = -SkFDot6ToFixed(fFace->glyph->advance.x);
   1136             glyph->fAdvanceY = SkFDot6ToFixed(fFace->glyph->advance.y);
   1137         }
   1138 
   1139     } else if ((fRec.fFlags & SkScalerContext::kVertical_Flag)
   1140                 && fFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
   1141 
   1142         //TODO: do we need to specially handle SubpixelPositioning and Kerning?
   1143 
   1144         FT_Matrix identityMatrix;
   1145         identityMatrix.xx = identityMatrix.yy = SK_Fixed1;
   1146         identityMatrix.xy = identityMatrix.yx = 0;
   1147 
   1148         // if the matrix is not the identity matrix then we need to re-load the
   1149         // glyph with the identity matrix to get the necessary bounding box
   1150         if (memcmp(&fMatrix22, &identityMatrix, sizeof(FT_Matrix)) != 0) {
   1151 
   1152             FT_Set_Transform(fFace, &identityMatrix, NULL);
   1153 
   1154             err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags );
   1155             if (err != 0) {
   1156                 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(glyph:%d flags:%d) returned 0x%x\n",
   1157                             fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, err));
   1158                 goto ERROR;
   1159             }
   1160 
   1161             if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) {
   1162                 emboldenOutline(&fFace->glyph->outline);
   1163             }
   1164         }
   1165 
   1166         // bounding box of the unskewed and unscaled glyph
   1167         FT_BBox bbox;
   1168         getBBoxForCurrentGlyph(glyph, &bbox);
   1169 
   1170         // compute the vertical gap above and below the glyph if the glyph were
   1171         // centered within the linearVertAdvance
   1172         SkFixed vGap = (fFace->glyph->linearVertAdvance - Dot6ToFixed(bbox.yMax - bbox.yMin)) / 2;
   1173 
   1174         // the origin point of the glyph when rendered vertically
   1175         FT_Vector vOrigin;
   1176         vOrigin.x = fFace->glyph->linearHoriAdvance / 2;
   1177         vOrigin.y = vGap + Dot6ToFixed(bbox.yMax);
   1178 
   1179         // transform the vertical origin based on the matrix of the actual glyph
   1180         FT_Vector_Transform(&vOrigin, &fMatrix22);
   1181 
   1182         // compute a new offset vector for the glyph by subtracting the vertical
   1183         // origin from the original horizontal offset vector
   1184         glyph->fLeft = SkFixedRoundToInt(vLeft - vOrigin.x);
   1185         glyph->fTop =  -SkFixedRoundToInt(vTop - vOrigin.y);
   1186 
   1187         updateGlyphIfLCD(glyph);
   1188 
   1189         // use the vertical advance values computed by freetype
   1190         glyph->fAdvanceX = -SkFixedMul(fMatrix22.xy, fFace->glyph->linearVertAdvance);
   1191         glyph->fAdvanceY = SkFixedMul(fMatrix22.yy, fFace->glyph->linearVertAdvance);
   1192     }
   1193 
   1194 
   1195 #ifdef ENABLE_GLYPH_SPEW
   1196     SkDEBUGF(("FT_Set_Char_Size(this:%p sx:%x sy:%x ", this, fScaleX, fScaleY));
   1197     SkDEBUGF(("Metrics(glyph:%d flags:0x%x) w:%d\n", glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFlags, glyph->fWidth));
   1198 #endif
   1199 }