LCOV - code coverage report
Current view: directory - gfx/skia/src/core - SkScalerContext.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 404 0 0.0 %
Date: 2012-06-02 Functions: 42 0 0.0 %

       1                 : 
       2                 : /*
       3                 :  * Copyright 2006 The Android Open Source Project
       4                 :  *
       5                 :  * Use of this source code is governed by a BSD-style license that can be
       6                 :  * found in the LICENSE file.
       7                 :  */
       8                 : 
       9                 : 
      10                 : #include "SkScalerContext.h"
      11                 : #include "SkColorPriv.h"
      12                 : #include "SkDescriptor.h"
      13                 : #include "SkDraw.h"
      14                 : #include "SkFontHost.h"
      15                 : #include "SkMaskFilter.h"
      16                 : #include "SkPathEffect.h"
      17                 : #include "SkRasterizer.h"
      18                 : #include "SkRasterClip.h"
      19                 : #include "SkStroke.h"
      20                 : #include "SkThread.h"
      21                 : 
      22                 : #define ComputeBWRowBytes(width)        (((unsigned)(width) + 7) >> 3)
      23                 : 
      24               0 : void SkGlyph::toMask(SkMask* mask) const {
      25               0 :     SkASSERT(mask);
      26                 : 
      27               0 :     mask->fImage = (uint8_t*)fImage;
      28               0 :     mask->fBounds.set(fLeft, fTop, fLeft + fWidth, fTop + fHeight);
      29               0 :     mask->fRowBytes = this->rowBytes();
      30               0 :     mask->fFormat = static_cast<SkMask::Format>(fMaskFormat);
      31               0 : }
      32                 : 
      33               0 : size_t SkGlyph::computeImageSize() const {
      34               0 :     const size_t size = this->rowBytes() * fHeight;
      35                 : 
      36               0 :     switch (fMaskFormat) {
      37                 :         case SkMask::k3D_Format:
      38               0 :             return 3 * size;
      39                 :         default:
      40               0 :             return size;
      41                 :     }
      42                 : }
      43                 : 
      44               0 : void SkGlyph::zeroMetrics() {
      45               0 :     fAdvanceX = 0;
      46               0 :     fAdvanceY = 0;
      47               0 :     fWidth    = 0;
      48               0 :     fHeight   = 0;
      49               0 :     fTop      = 0;
      50               0 :     fLeft     = 0;
      51               0 :     fRsbDelta = 0;
      52               0 :     fLsbDelta = 0;
      53               0 : }
      54                 : 
      55                 : ///////////////////////////////////////////////////////////////////////////////
      56                 : 
      57                 : #ifdef SK_DEBUG
      58                 :     #define DUMP_RECx
      59                 : #endif
      60                 : 
      61               0 : static SkFlattenable* load_flattenable(const SkDescriptor* desc, uint32_t tag) {
      62               0 :     SkFlattenable*  obj = NULL;
      63                 :     uint32_t        len;
      64               0 :     const void*     data = desc->findEntry(tag, &len);
      65                 : 
      66               0 :     if (data) {
      67               0 :         SkFlattenableReadBuffer   buffer(data, len);
      68               0 :         obj = buffer.readFlattenable();
      69               0 :         SkASSERT(buffer.offset() == buffer.size());
      70                 :     }
      71               0 :     return obj;
      72                 : }
      73                 : 
      74               0 : SkScalerContext::SkScalerContext(const SkDescriptor* desc)
      75               0 :     : fPathEffect(NULL), fMaskFilter(NULL)
      76                 : {
      77               0 :     fBaseGlyphCount = 0;
      78               0 :     fNextContext = NULL;
      79                 : 
      80               0 :     const Rec* rec = (const Rec*)desc->findEntry(kRec_SkDescriptorTag, NULL);
      81               0 :     SkASSERT(rec);
      82                 : 
      83               0 :     fRec = *rec;
      84                 : 
      85                 : #ifdef DUMP_REC
      86                 :     desc->assertChecksum();
      87                 :     SkDebugf("SkScalarContext checksum %x count %d length %d\n",
      88                 :              desc->getChecksum(), desc->getCount(), desc->getLength());
      89                 :     SkDebugf(" textsize %g prescale %g preskew %g post [%g %g %g %g]\n",
      90                 :         rec->fTextSize, rec->fPreScaleX, rec->fPreSkewX, rec->fPost2x2[0][0],
      91                 :         rec->fPost2x2[0][1], rec->fPost2x2[1][0], rec->fPost2x2[1][1]);
      92                 :     SkDebugf("  frame %g miter %g hints %d framefill %d format %d join %d\n",
      93                 :         rec->fFrameWidth, rec->fMiterLimit, rec->fHints, rec->fFrameAndFill,
      94                 :         rec->fMaskFormat, rec->fStrokeJoin);
      95                 :     SkDebugf("  pathEffect %x maskFilter %x\n",
      96                 :              desc->findEntry(kPathEffect_SkDescriptorTag, NULL),
      97                 :         desc->findEntry(kMaskFilter_SkDescriptorTag, NULL));
      98                 : #endif
      99                 : 
     100               0 :     fPathEffect = (SkPathEffect*)load_flattenable(desc, kPathEffect_SkDescriptorTag);
     101               0 :     fMaskFilter = (SkMaskFilter*)load_flattenable(desc, kMaskFilter_SkDescriptorTag);
     102               0 :     fRasterizer = (SkRasterizer*)load_flattenable(desc, kRasterizer_SkDescriptorTag);
     103                 : 
     104                 :     // initialize based on our settings. subclasses can also force this
     105                 :     fGenerateImageFromPath = fRec.fFrameWidth > 0 || fPathEffect != NULL ||
     106               0 :                              fRasterizer != NULL;
     107               0 : }
     108                 : 
     109               0 : SkScalerContext::~SkScalerContext() {
     110               0 :     SkDELETE(fNextContext);
     111                 : 
     112               0 :     SkSafeUnref(fPathEffect);
     113               0 :     SkSafeUnref(fMaskFilter);
     114               0 :     SkSafeUnref(fRasterizer);
     115               0 : }
     116                 : 
     117               0 : static SkScalerContext* allocNextContext(const SkScalerContext::Rec& rec) {
     118                 :     // fonthost will determine the next possible font to search, based
     119                 :     // on the current font in fRec. It will return NULL if ctx is our
     120                 :     // last font that can be searched (i.e. ultimate fallback font)
     121               0 :     uint32_t newFontID = SkFontHost::NextLogicalFont(rec.fFontID, rec.fOrigFontID);
     122               0 :     if (0 == newFontID) {
     123               0 :         return NULL;
     124                 :     }
     125                 : 
     126               0 :     SkAutoDescriptor    ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
     127               0 :     SkDescriptor*       desc = ad.getDesc();
     128                 : 
     129               0 :     desc->init();
     130                 :     SkScalerContext::Rec* newRec =
     131                 :     (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
     132               0 :                                           sizeof(rec), &rec);
     133               0 :     newRec->fFontID = newFontID;
     134               0 :     desc->computeChecksum();
     135                 : 
     136               0 :     return SkFontHost::CreateScalerContext(desc);
     137                 : }
     138                 : 
     139                 : /*  Return the next context, creating it if its not already created, but return
     140                 :     NULL if the fonthost says there are no more fonts to fallback to.
     141                 :  */
     142               0 : SkScalerContext* SkScalerContext::getNextContext() {
     143               0 :     SkScalerContext* next = fNextContext;
     144                 :     // if next is null, then either it isn't cached yet, or we're at the
     145                 :     // end of our possible chain
     146               0 :     if (NULL == next) {
     147               0 :         next = allocNextContext(fRec);
     148               0 :         if (NULL == next) {
     149               0 :             return NULL;
     150                 :         }
     151                 :         // next's base is our base + our local count
     152               0 :         next->setBaseGlyphCount(fBaseGlyphCount + this->getGlyphCount());
     153                 :         // cache the answer
     154               0 :         fNextContext = next;
     155                 :     }
     156               0 :     return next;
     157                 : }
     158                 : 
     159               0 : SkScalerContext* SkScalerContext::getGlyphContext(const SkGlyph& glyph) {
     160               0 :     unsigned glyphID = glyph.getGlyphID();
     161               0 :     SkScalerContext* ctx = this;
     162               0 :     for (;;) {
     163               0 :         unsigned count = ctx->getGlyphCount();
     164               0 :         if (glyphID < count) {
     165                 :             break;
     166                 :         }
     167               0 :         glyphID -= count;
     168               0 :         ctx = ctx->getNextContext();
     169               0 :         if (NULL == ctx) {
     170               0 :             SkDebugf("--- no context for glyph %x\n", glyph.getGlyphID());
     171                 :             // just return the original context (this)
     172               0 :             return this;
     173                 :         }
     174                 :     }
     175               0 :     return ctx;
     176                 : }
     177                 : 
     178                 : /*  This loops through all available fallback contexts (if needed) until it
     179                 :     finds some context that can handle the unichar. If all fail, returns 0
     180                 :  */
     181               0 : uint16_t SkScalerContext::charToGlyphID(SkUnichar uni) {
     182               0 :     SkScalerContext* ctx = this;
     183                 :     unsigned glyphID;
     184               0 :     for (;;) {
     185               0 :         glyphID = ctx->generateCharToGlyph(uni);
     186               0 :         if (glyphID) {
     187                 :             break;  // found it
     188                 :         }
     189               0 :         ctx = ctx->getNextContext();
     190               0 :         if (NULL == ctx) {
     191               0 :             return 0;   // no more contexts, return missing glyph
     192                 :         }
     193                 :     }
     194                 :     // add the ctx's base, making glyphID unique for chain of contexts
     195               0 :     glyphID += ctx->fBaseGlyphCount;
     196                 :     // check for overflow of 16bits, since our glyphID cannot exceed that
     197               0 :     if (glyphID > 0xFFFF) {
     198               0 :         glyphID = 0;
     199                 :     }
     200               0 :     return SkToU16(glyphID);
     201                 : }
     202                 : 
     203               0 : SkUnichar SkScalerContext::glyphIDToChar(uint16_t glyphID) {
     204               0 :     SkScalerContext* ctx = this;
     205               0 :     unsigned rangeEnd = 0;
     206               0 :     do {
     207               0 :         unsigned rangeStart = rangeEnd;
     208                 : 
     209               0 :         rangeEnd += ctx->getGlyphCount();
     210               0 :         if (rangeStart <= glyphID && glyphID < rangeEnd) {
     211               0 :             return ctx->generateGlyphToChar(glyphID - rangeStart);
     212                 :         }
     213               0 :         ctx = ctx->getNextContext();
     214                 :     } while (NULL != ctx);
     215               0 :     return 0;
     216                 : }
     217                 : 
     218               0 : void SkScalerContext::getAdvance(SkGlyph* glyph) {
     219                 :     // mark us as just having a valid advance
     220               0 :     glyph->fMaskFormat = MASK_FORMAT_JUST_ADVANCE;
     221                 :     // we mark the format before making the call, in case the impl
     222                 :     // internally ends up calling its generateMetrics, which is OK
     223                 :     // albeit slower than strictly necessary
     224               0 :     this->getGlyphContext(*glyph)->generateAdvance(glyph);
     225               0 : }
     226                 : 
     227               0 : void SkScalerContext::getMetrics(SkGlyph* glyph) {
     228               0 :     this->getGlyphContext(*glyph)->generateMetrics(glyph);
     229                 : 
     230                 :     // for now we have separate cache entries for devkerning on and off
     231                 :     // in the future we might share caches, but make our measure/draw
     232                 :     // code make the distinction. Thus we zap the values if the caller
     233                 :     // has not asked for them.
     234               0 :     if ((fRec.fFlags & SkScalerContext::kDevKernText_Flag) == 0) {
     235                 :         // no devkern, so zap the fields
     236               0 :         glyph->fLsbDelta = glyph->fRsbDelta = 0;
     237                 :     }
     238                 : 
     239                 :     // if either dimension is empty, zap the image bounds of the glyph
     240               0 :     if (0 == glyph->fWidth || 0 == glyph->fHeight) {
     241               0 :         glyph->fWidth   = 0;
     242               0 :         glyph->fHeight  = 0;
     243               0 :         glyph->fTop     = 0;
     244               0 :         glyph->fLeft    = 0;
     245               0 :         glyph->fMaskFormat = 0;
     246               0 :         return;
     247                 :     }
     248                 : 
     249               0 :     if (fGenerateImageFromPath) {
     250               0 :         SkPath      devPath, fillPath;
     251                 :         SkMatrix    fillToDevMatrix;
     252                 : 
     253               0 :         this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
     254                 : 
     255               0 :         if (fRasterizer) {
     256                 :             SkMask  mask;
     257                 : 
     258               0 :             if (fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
     259                 :                                        fMaskFilter, &mask,
     260               0 :                                        SkMask::kJustComputeBounds_CreateMode)) {
     261               0 :                 glyph->fLeft    = mask.fBounds.fLeft;
     262               0 :                 glyph->fTop     = mask.fBounds.fTop;
     263               0 :                 glyph->fWidth   = SkToU16(mask.fBounds.width());
     264               0 :                 glyph->fHeight  = SkToU16(mask.fBounds.height());
     265                 :             } else {
     266                 :                 goto SK_ERROR;
     267                 :             }
     268                 :         } else {
     269                 :             // just use devPath
     270                 :             SkIRect ir;
     271               0 :             devPath.getBounds().roundOut(&ir);
     272                 : 
     273               0 :             if (ir.isEmpty() || !ir.is16Bit()) {
     274                 :                 goto SK_ERROR;
     275                 :             }
     276               0 :             glyph->fLeft    = ir.fLeft;
     277               0 :             glyph->fTop     = ir.fTop;
     278               0 :             glyph->fWidth   = SkToU16(ir.width());
     279               0 :             glyph->fHeight  = SkToU16(ir.height());
     280                 :         }
     281                 :     }
     282                 : 
     283               0 :         if (SkMask::kARGB32_Format != glyph->fMaskFormat) {
     284               0 :                 glyph->fMaskFormat = fRec.fMaskFormat;
     285                 :         }
     286                 : 
     287               0 :     if (fMaskFilter) {
     288                 :         SkMask      src, dst;
     289                 :         SkMatrix    matrix;
     290                 : 
     291               0 :         glyph->toMask(&src);
     292               0 :         fRec.getMatrixFrom2x2(&matrix);
     293                 : 
     294               0 :         src.fImage = NULL;  // only want the bounds from the filter
     295               0 :         if (fMaskFilter->filterMask(&dst, src, matrix, NULL)) {
     296               0 :             SkASSERT(dst.fImage == NULL);
     297               0 :             glyph->fLeft    = dst.fBounds.fLeft;
     298               0 :             glyph->fTop     = dst.fBounds.fTop;
     299               0 :             glyph->fWidth   = SkToU16(dst.fBounds.width());
     300               0 :             glyph->fHeight  = SkToU16(dst.fBounds.height());
     301               0 :             glyph->fMaskFormat = dst.fFormat;
     302                 :         }
     303                 :     }
     304               0 :     return;
     305                 : 
     306                 : SK_ERROR:
     307                 :     // draw nothing 'cause we failed
     308               0 :     glyph->fLeft    = 0;
     309               0 :     glyph->fTop     = 0;
     310               0 :     glyph->fWidth   = 0;
     311               0 :     glyph->fHeight  = 0;
     312                 :     // put a valid value here, in case it was earlier set to
     313                 :     // MASK_FORMAT_JUST_ADVANCE
     314               0 :     glyph->fMaskFormat = fRec.fMaskFormat;
     315                 : }
     316                 : 
     317               0 : static bool isLCD(const SkScalerContext::Rec& rec) {
     318                 :     return SkMask::kLCD16_Format == rec.fMaskFormat ||
     319               0 :            SkMask::kLCD32_Format == rec.fMaskFormat;
     320                 : }
     321                 : 
     322               0 : static uint16_t a8_to_rgb565(unsigned a8) {
     323               0 :     return SkPackRGB16(a8 >> 3, a8 >> 2, a8 >> 3);
     324                 : }
     325                 : 
     326               0 : static void copyToLCD16(const SkBitmap& src, const SkMask& dst) {
     327               0 :     SkASSERT(SkBitmap::kA8_Config == src.config());
     328               0 :     SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
     329                 : 
     330               0 :     const int width = dst.fBounds.width();
     331               0 :     const int height = dst.fBounds.height();
     332               0 :     const uint8_t* srcP = src.getAddr8(0, 0);
     333               0 :     size_t srcRB = src.rowBytes();
     334               0 :     uint16_t* dstP = (uint16_t*)dst.fImage;
     335               0 :     size_t dstRB = dst.fRowBytes;
     336               0 :     for (int y = 0; y < height; ++y) {
     337               0 :         for (int x = 0; x < width; ++x) {
     338               0 :             dstP[x] = a8_to_rgb565(srcP[x]);
     339                 :         }
     340               0 :         srcP += srcRB;
     341               0 :         dstP = (uint16_t*)((char*)dstP + dstRB);
     342                 :     }
     343               0 : }
     344                 : 
     345                 : #define SK_FREETYPE_LCD_LERP    160
     346                 : 
     347               0 : static int lerp(int start, int end) {
     348                 :     SkASSERT((unsigned)SK_FREETYPE_LCD_LERP <= 256);
     349               0 :     return start + ((end - start) * (SK_FREETYPE_LCD_LERP) >> 8);
     350                 : }
     351                 : 
     352               0 : static uint16_t packLCD16(unsigned r, unsigned g, unsigned b) {
     353                 :     if (SK_FREETYPE_LCD_LERP) {
     354                 :         // want (a+b+c)/3, but we approx to avoid the divide
     355               0 :         unsigned ave = (5 * (r + g + b) + g) >> 4;
     356               0 :         r = lerp(r, ave);
     357               0 :         g = lerp(g, ave);
     358               0 :         b = lerp(b, ave);
     359                 :     }
     360               0 :     return SkPackRGB16(r >> 3, g >> 2, b >> 3);
     361                 : }
     362                 : 
     363               0 : static void pack3xHToLCD16(const SkBitmap& src, const SkMask& dst) {
     364               0 :     SkASSERT(SkBitmap::kA8_Config == src.config());
     365               0 :     SkASSERT(SkMask::kLCD16_Format == dst.fFormat);
     366                 :     
     367               0 :     const int width = dst.fBounds.width();
     368               0 :     const int height = dst.fBounds.height();
     369               0 :     uint16_t* dstP = (uint16_t*)dst.fImage;
     370               0 :     size_t dstRB = dst.fRowBytes;
     371               0 :     for (int y = 0; y < height; ++y) {
     372               0 :         const uint8_t* srcP = src.getAddr8(0, y);
     373               0 :         for (int x = 0; x < width; ++x) {
     374               0 :             unsigned r = *srcP++;
     375               0 :             unsigned g = *srcP++;
     376               0 :             unsigned b = *srcP++;
     377               0 :             dstP[x] = packLCD16(r, g, b);
     378                 :         }
     379               0 :         dstP = (uint16_t*)((char*)dstP + dstRB);
     380                 :     }
     381               0 : }
     382                 : 
     383               0 : static void pack3xHToLCD32(const SkBitmap& src, const SkMask& dst) {
     384               0 :     SkASSERT(SkBitmap::kA8_Config == src.config());
     385               0 :     SkASSERT(SkMask::kLCD32_Format == dst.fFormat);
     386                 :     
     387               0 :     const int width = dst.fBounds.width();
     388               0 :     const int height = dst.fBounds.height();
     389               0 :     SkPMColor* dstP = (SkPMColor*)dst.fImage;
     390               0 :     size_t dstRB = dst.fRowBytes;
     391               0 :     for (int y = 0; y < height; ++y) {
     392               0 :         const uint8_t* srcP = src.getAddr8(0, y);
     393               0 :         for (int x = 0; x < width; ++x) {
     394               0 :             unsigned r = *srcP++;
     395               0 :             unsigned g = *srcP++;
     396               0 :             unsigned b = *srcP++;
     397               0 :             unsigned a = SkMax32(SkMax32(r, g), b);
     398               0 :             dstP[x] = SkPackARGB32(a, r, g, b);
     399                 :         }
     400               0 :         dstP = (SkPMColor*)((char*)dstP + dstRB);
     401                 :     }
     402               0 : }
     403                 : 
     404               0 : static void generateMask(const SkMask& mask, const SkPath& path) {
     405                 :     SkBitmap::Config config;
     406               0 :     SkPaint     paint;
     407                 : 
     408               0 :     int srcW = mask.fBounds.width();
     409               0 :     int srcH = mask.fBounds.height();
     410               0 :     int dstW = srcW;
     411               0 :     int dstH = srcH;
     412               0 :     int dstRB = mask.fRowBytes;
     413                 : 
     414                 :     SkMatrix matrix;
     415               0 :     matrix.setTranslate(-SkIntToScalar(mask.fBounds.fLeft),
     416               0 :                         -SkIntToScalar(mask.fBounds.fTop));
     417                 : 
     418               0 :     if (SkMask::kBW_Format == mask.fFormat) {
     419               0 :         config = SkBitmap::kA1_Config;
     420               0 :         paint.setAntiAlias(false);
     421                 :     } else {
     422               0 :         config = SkBitmap::kA8_Config;
     423               0 :         paint.setAntiAlias(true);
     424               0 :         switch (mask.fFormat) {
     425                 :             case SkMask::kA8_Format:
     426               0 :                 break;
     427                 :             case SkMask::kLCD16_Format:
     428                 :             case SkMask::kLCD32_Format:
     429                 :                 // TODO: trigger off LCD orientation
     430               0 :                 dstW *= 3;
     431               0 :                 matrix.postScale(SkIntToScalar(3), SK_Scalar1);
     432               0 :                 dstRB = 0;  // signals we need a copy
     433               0 :                 break;
     434                 :             default:
     435               0 :                 SkDEBUGFAIL("unexpected mask format");
     436                 :         }
     437                 :     }
     438                 : 
     439               0 :     SkRasterClip clip;
     440               0 :     clip.setRect(SkIRect::MakeWH(dstW, dstH));
     441                 : 
     442               0 :     SkBitmap bm;
     443               0 :     bm.setConfig(config, dstW, dstH, dstRB);
     444                 : 
     445               0 :     if (0 == dstRB) {
     446               0 :         bm.allocPixels();
     447               0 :         bm.lockPixels();
     448                 :     } else {
     449               0 :         bm.setPixels(mask.fImage);
     450                 :     }
     451               0 :     sk_bzero(bm.getPixels(), bm.getSafeSize());
     452                 :     
     453               0 :     SkDraw  draw;
     454               0 :     sk_bzero(&draw, sizeof(draw));
     455               0 :     draw.fRC    = &clip;
     456               0 :     draw.fClip  = &clip.bwRgn();
     457               0 :     draw.fMatrix = &matrix;
     458               0 :     draw.fBitmap = &bm;
     459               0 :     draw.drawPath(path, paint);
     460                 :     
     461               0 :     if (0 == dstRB) {
     462               0 :         switch (mask.fFormat) {
     463                 :             case SkMask::kLCD16_Format:
     464               0 :                 pack3xHToLCD16(bm, mask);
     465               0 :                 break;
     466                 :             case SkMask::kLCD32_Format:
     467               0 :                 pack3xHToLCD32(bm, mask);
     468               0 :                 break;
     469                 :             default:
     470               0 :                 SkDEBUGFAIL("bad format for copyback");
     471                 :         }
     472                 :     }
     473               0 : }
     474                 : 
     475               0 : void SkScalerContext::getImage(const SkGlyph& origGlyph) {
     476               0 :     const SkGlyph*  glyph = &origGlyph;
     477                 :     SkGlyph         tmpGlyph;
     478                 : 
     479               0 :     if (fMaskFilter) {   // restore the prefilter bounds
     480               0 :         tmpGlyph.init(origGlyph.fID);
     481                 : 
     482                 :         // need the original bounds, sans our maskfilter
     483               0 :         SkMaskFilter* mf = fMaskFilter;
     484               0 :         fMaskFilter = NULL;             // temp disable
     485               0 :         this->getMetrics(&tmpGlyph);
     486               0 :         fMaskFilter = mf;               // restore
     487                 : 
     488               0 :         tmpGlyph.fImage = origGlyph.fImage;
     489                 : 
     490                 :         // we need the prefilter bounds to be <= filter bounds
     491               0 :         SkASSERT(tmpGlyph.fWidth <= origGlyph.fWidth);
     492               0 :         SkASSERT(tmpGlyph.fHeight <= origGlyph.fHeight);
     493               0 :         glyph = &tmpGlyph;
     494                 :     }
     495                 : 
     496               0 :     if (fGenerateImageFromPath) {
     497               0 :         SkPath      devPath, fillPath;
     498                 :         SkMatrix    fillToDevMatrix;
     499                 :         SkMask      mask;
     500                 : 
     501               0 :         this->internalGetPath(*glyph, &fillPath, &devPath, &fillToDevMatrix);
     502               0 :         glyph->toMask(&mask);
     503                 : 
     504               0 :         if (fRasterizer) {
     505               0 :             mask.fFormat = SkMask::kA8_Format;
     506               0 :             sk_bzero(glyph->fImage, mask.computeImageSize());
     507                 : 
     508               0 :             if (!fRasterizer->rasterize(fillPath, fillToDevMatrix, NULL,
     509                 :                                         fMaskFilter, &mask,
     510               0 :                                         SkMask::kJustRenderImage_CreateMode)) {
     511                 :                 return;
     512                 :             }
     513                 :         } else {
     514               0 :             generateMask(mask, devPath);
     515                 :         }
     516                 :     } else {
     517               0 :         this->getGlyphContext(*glyph)->generateImage(*glyph);
     518                 :     }
     519                 : 
     520               0 :     if (fMaskFilter) {
     521                 :         SkMask      srcM, dstM;
     522                 :         SkMatrix    matrix;
     523                 : 
     524                 :         // the src glyph image shouldn't be 3D
     525               0 :         SkASSERT(SkMask::k3D_Format != glyph->fMaskFormat);
     526               0 :         glyph->toMask(&srcM);
     527               0 :         fRec.getMatrixFrom2x2(&matrix);
     528                 : 
     529               0 :         if (fMaskFilter->filterMask(&dstM, srcM, matrix, NULL)) {
     530               0 :             int width = SkFastMin32(origGlyph.fWidth, dstM.fBounds.width());
     531               0 :             int height = SkFastMin32(origGlyph.fHeight, dstM.fBounds.height());
     532               0 :             int dstRB = origGlyph.rowBytes();
     533               0 :             int srcRB = dstM.fRowBytes;
     534                 : 
     535               0 :             const uint8_t* src = (const uint8_t*)dstM.fImage;
     536               0 :             uint8_t* dst = (uint8_t*)origGlyph.fImage;
     537                 : 
     538               0 :             if (SkMask::k3D_Format == dstM.fFormat) {
     539                 :                 // we have to copy 3 times as much
     540               0 :                 height *= 3;
     541                 :             }
     542                 : 
     543                 :             // clean out our glyph, since it may be larger than dstM
     544                 :             //sk_bzero(dst, height * dstRB);
     545                 : 
     546               0 :             while (--height >= 0) {
     547               0 :                 memcpy(dst, src, width);
     548               0 :                 src += srcRB;
     549               0 :                 dst += dstRB;
     550                 :             }
     551               0 :             SkMask::FreeImage(dstM.fImage);
     552                 :         }
     553                 :     }
     554                 : }
     555                 : 
     556               0 : void SkScalerContext::getPath(const SkGlyph& glyph, SkPath* path) {
     557               0 :     this->internalGetPath(glyph, NULL, path, NULL);
     558               0 : }
     559                 : 
     560               0 : void SkScalerContext::getFontMetrics(SkPaint::FontMetrics* mx,
     561                 :                                      SkPaint::FontMetrics* my) {
     562               0 :     this->generateFontMetrics(mx, my);
     563               0 : }
     564                 : 
     565               0 : SkUnichar SkScalerContext::generateGlyphToChar(uint16_t glyph) {
     566               0 :     return 0;
     567                 : }
     568                 : 
     569                 : ///////////////////////////////////////////////////////////////////////////////
     570                 : 
     571               0 : void SkScalerContext::internalGetPath(const SkGlyph& glyph, SkPath* fillPath,
     572                 :                                   SkPath* devPath, SkMatrix* fillToDevMatrix) {
     573               0 :     SkPath  path;
     574                 : 
     575               0 :     this->getGlyphContext(glyph)->generatePath(glyph, &path);
     576                 : 
     577               0 :     if (fRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag) {
     578               0 :         SkFixed dx = glyph.getSubXFixed();
     579               0 :         SkFixed dy = glyph.getSubYFixed();
     580               0 :         if (dx | dy) {
     581               0 :             path.offset(SkFixedToScalar(dx), SkFixedToScalar(dy));
     582                 :         }
     583                 :     }
     584                 : 
     585               0 :     if (fRec.fFrameWidth > 0 || fPathEffect != NULL) {
     586                 :         // need the path in user-space, with only the point-size applied
     587                 :         // so that our stroking and effects will operate the same way they
     588                 :         // would if the user had extracted the path themself, and then
     589                 :         // called drawPath
     590               0 :         SkPath      localPath;
     591                 :         SkMatrix    matrix, inverse;
     592                 : 
     593               0 :         fRec.getMatrixFrom2x2(&matrix);
     594               0 :         matrix.invert(&inverse);
     595               0 :         path.transform(inverse, &localPath);
     596                 :         // now localPath is only affected by the paint settings, and not the canvas matrix
     597                 : 
     598               0 :         SkScalar width = fRec.fFrameWidth;
     599                 : 
     600               0 :         if (fPathEffect) {
     601               0 :             SkPath effectPath;
     602                 : 
     603               0 :             if (fPathEffect->filterPath(&effectPath, localPath, &width)) {
     604               0 :                 localPath.swap(effectPath);
     605                 :             }
     606                 :         }
     607                 : 
     608               0 :         if (width > 0) {
     609               0 :             SkStroke    stroker;
     610               0 :             SkPath      outline;
     611                 : 
     612               0 :             stroker.setWidth(width);
     613               0 :             stroker.setMiterLimit(fRec.fMiterLimit);
     614               0 :             stroker.setJoin((SkPaint::Join)fRec.fStrokeJoin);
     615               0 :             stroker.setDoFill(SkToBool(fRec.fFlags & kFrameAndFill_Flag));
     616               0 :             stroker.strokePath(localPath, &outline);
     617               0 :             localPath.swap(outline);
     618                 :         }
     619                 : 
     620                 :         // now return stuff to the caller
     621               0 :         if (fillToDevMatrix) {
     622               0 :             *fillToDevMatrix = matrix;
     623                 :         }
     624               0 :         if (devPath) {
     625               0 :             localPath.transform(matrix, devPath);
     626                 :         }
     627               0 :         if (fillPath) {
     628               0 :             fillPath->swap(localPath);
     629               0 :         }
     630                 :     } else {   // nothing tricky to do
     631               0 :         if (fillToDevMatrix) {
     632               0 :             fillToDevMatrix->reset();
     633                 :         }
     634               0 :         if (devPath) {
     635               0 :             if (fillPath == NULL) {
     636               0 :                 devPath->swap(path);
     637                 :             } else {
     638               0 :                 *devPath = path;
     639                 :             }
     640                 :         }
     641                 : 
     642               0 :         if (fillPath) {
     643               0 :             fillPath->swap(path);
     644                 :         }
     645                 :     }
     646                 : 
     647               0 :     if (devPath) {
     648               0 :         devPath->updateBoundsCache();
     649                 :     }
     650               0 :     if (fillPath) {
     651               0 :         fillPath->updateBoundsCache();
     652                 :     }
     653               0 : }
     654                 : 
     655                 : 
     656               0 : void SkScalerContext::Rec::getMatrixFrom2x2(SkMatrix* dst) const {
     657               0 :     dst->reset();
     658               0 :     dst->setScaleX(fPost2x2[0][0]);
     659               0 :     dst->setSkewX( fPost2x2[0][1]);
     660               0 :     dst->setSkewY( fPost2x2[1][0]);
     661               0 :     dst->setScaleY(fPost2x2[1][1]);
     662               0 : }
     663                 : 
     664               0 : void SkScalerContext::Rec::getLocalMatrix(SkMatrix* m) const {
     665               0 :     m->setScale(SkScalarMul(fTextSize, fPreScaleX), fTextSize);
     666               0 :     if (fPreSkewX) {
     667               0 :         m->postSkew(fPreSkewX, 0);
     668                 :     }
     669               0 : }
     670                 : 
     671               0 : void SkScalerContext::Rec::getSingleMatrix(SkMatrix* m) const {
     672               0 :     this->getLocalMatrix(m);
     673                 : 
     674                 :     //  now concat the device matrix
     675                 :     SkMatrix    deviceMatrix;
     676               0 :     this->getMatrixFrom2x2(&deviceMatrix);
     677               0 :     m->postConcat(deviceMatrix);
     678               0 : }
     679                 : 
     680               0 : SkAxisAlignment SkComputeAxisAlignmentForHText(const SkMatrix& matrix) {
     681               0 :     SkASSERT(!matrix.hasPerspective());
     682                 :     
     683               0 :     if (0 == matrix[SkMatrix::kMSkewY]) {
     684               0 :         return kX_SkAxisAlignment;
     685                 :     }
     686               0 :     if (0 == matrix[SkMatrix::kMScaleX]) {
     687               0 :         return kY_SkAxisAlignment;
     688                 :     }
     689               0 :     return kNone_SkAxisAlignment;
     690                 : }
     691                 : 
     692                 : ///////////////////////////////////////////////////////////////////////////////
     693                 : 
     694                 : #include "SkFontHost.h"
     695                 : 
     696               0 : class SkScalerContext_Empty : public SkScalerContext {
     697                 : public:
     698               0 :     SkScalerContext_Empty(const SkDescriptor* desc) : SkScalerContext(desc) {}
     699                 : 
     700                 : protected:
     701               0 :     virtual unsigned generateGlyphCount() {
     702               0 :         return 0;
     703                 :     }
     704               0 :     virtual uint16_t generateCharToGlyph(SkUnichar uni) {
     705               0 :         return 0;
     706                 :     }
     707               0 :     virtual void generateAdvance(SkGlyph* glyph) {
     708               0 :         glyph->zeroMetrics();
     709               0 :     }
     710               0 :     virtual void generateMetrics(SkGlyph* glyph) {
     711               0 :         glyph->zeroMetrics();
     712               0 :     }
     713               0 :     virtual void generateImage(const SkGlyph& glyph) {}
     714               0 :     virtual void generatePath(const SkGlyph& glyph, SkPath* path) {}
     715               0 :     virtual void generateFontMetrics(SkPaint::FontMetrics* mx,
     716                 :                                      SkPaint::FontMetrics* my) {
     717               0 :         if (mx) {
     718               0 :             sk_bzero(mx, sizeof(*mx));
     719                 :         }
     720               0 :         if (my) {
     721               0 :             sk_bzero(my, sizeof(*my));
     722                 :         }
     723               0 :     }
     724                 : };
     725                 : 
     726                 : extern SkScalerContext* SkCreateColorScalerContext(const SkDescriptor* desc);
     727                 : 
     728               0 : SkScalerContext* SkScalerContext::Create(const SkDescriptor* desc) {
     729               0 :         SkScalerContext* c = NULL;  //SkCreateColorScalerContext(desc);
     730               0 :         if (NULL == c) {
     731               0 :                 c = SkFontHost::CreateScalerContext(desc);
     732                 :         }
     733               0 :     if (NULL == c) {
     734               0 :         c = SkNEW_ARGS(SkScalerContext_Empty, (desc));
     735                 :     }
     736               0 :     return c;
     737                 : }
     738                 : 

Generated by: LCOV version 1.7