Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: src/core/SkDraw.cpp

Issue 1403573002: Simplify draw one glyph (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address comments. Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 #define __STDC_LIMIT_MACROS 7 #define __STDC_LIMIT_MACROS
8 8
9 #include "SkDraw.h" 9 #include "SkDraw.h"
10 #include "SkBlitter.h" 10 #include "SkBlitter.h"
(...skipping 1405 matching lines...) Expand 10 before | Expand all | Expand 10 after
1416 } 1416 }
1417 } 1417 }
1418 1418
1419 // disable warning : local variable used without having been initialized 1419 // disable warning : local variable used without having been initialized
1420 #if defined _WIN32 && _MSC_VER >= 1300 1420 #if defined _WIN32 && _MSC_VER >= 1300
1421 #pragma warning ( push ) 1421 #pragma warning ( push )
1422 #pragma warning ( disable : 4701 ) 1422 #pragma warning ( disable : 4701 )
1423 #endif 1423 #endif
1424 1424
1425 //////////////////////////////////////////////////////////////////////////////// //////////////////// 1425 //////////////////////////////////////////////////////////////////////////////// ////////////////////
1426 struct SkDraw1Glyph {
1427 const SkDraw* fDraw;
1428 const SkRegion* fClip;
1429 const SkAAClip* fAAClip;
1430 SkBlitter* fBlitter;
1431 SkGlyphCache* fCache;
1432 const SkPaint* fPaint;
1433 SkIRect fClipBounds;
1434 /** Half the sampling frequency of the rasterized glyph in x. */
1435 SkScalar fHalfSampleX;
1436 /** Half the sampling frequency of the rasterized glyph in y. */
1437 SkScalar fHalfSampleY;
1438 1426
1439 /** Draws one glyph. 1427 class DrawOneGlyph {
1440 * 1428 public:
1441 * The x and y are pre-biased, so implementations may just truncate them. 1429 DrawOneGlyph(const SkDraw& draw, const SkPaint& paint, SkGlyphCache* cache, SkBlitter* blitter)
1442 * i.e. half the sampling frequency has been added. 1430 : fUseRegionToDraw(UsingRegionToDraw(draw.fRC))
1443 * e.g. 1/2 or 1/(2^(SkGlyph::kSubBits+1)) has already been added. 1431 , fGlyphCache(cache)
1444 * This added bias can be found in fHalfSampleX,Y. 1432 , fBlitter(blitter)
1445 */ 1433 , fClip(fUseRegionToDraw ? &draw.fRC->bwRgn() : nullptr)
1446 typedef void (*Proc)(const SkDraw1Glyph&, Sk48Dot16 x, Sk48Dot16 y, const Sk Glyph&); 1434 , fDraw(draw)
1435 , fPaint(paint)
1436 , fClipBounds(PickClipBounds(draw)) { }
1447 1437
1448 Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache, 1438 void operator()(const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
1449 const SkPaint&); 1439 position += rounding;
1440 Sk48Dot16 fx = SkScalarTo48Dot16(position.fX);
1441 Sk48Dot16 fy = SkScalarTo48Dot16(position.fY);
1442 // Prevent glyphs from being drawn outside of or straddling the edge of device space.
1443 if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1444 (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) ||
1445 (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1446 (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) {
1447 return;
1448 }
1450 1449
1451 // call this instead of fBlitter->blitMask() since this wrapper will handle 1450 int left = Sk48Dot16FloorToInt(fx);
1452 // the case when the mask is ARGB32_Format 1451 int top = Sk48Dot16FloorToInt(fy);
1453 // 1452 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1453
1454 left += glyph.fLeft;
1455 top += glyph.fTop;
1456
1457 int right = left + glyph.fWidth;
1458 int bottom = top + glyph.fHeight;
1459
1460 SkMask mask;
1461 mask.fBounds.set(left, top, right, bottom);
1462
1463 if (fUseRegionToDraw) {
1464 SkRegion::Cliperator clipper(*fClip, mask.fBounds);
1465
1466 if (!clipper.done() && this->getImageData(glyph, &mask)) {
1467 const SkIRect& cr = clipper.rect();
1468 do {
1469 this->blitMask(mask, cr);
1470 clipper.next();
1471 } while (!clipper.done());
1472 }
1473 } else {
1474 SkIRect storage;
1475 SkIRect* bounds = &mask.fBounds;
1476
1477 // this extra test is worth it, assuming that most of the time it su cceeds
1478 // since we can avoid writing to storage
1479 if (!fClipBounds.containsNoEmptyCheck(mask.fBounds)) {
1480 if (!storage.intersectNoEmptyCheck(mask.fBounds, fClipBounds))
1481 return;
1482 bounds = &storage;
1483 }
1484
1485 if (this->getImageData(glyph, &mask)) {
1486 this->blitMask(mask, *bounds);
1487 }
1488 }
1489 }
1490
1491 private:
1492 static bool UsingRegionToDraw(const SkRasterClip* rClip) {
1493 return rClip->isBW() && !rClip->isRect();
1494 }
1495
1496 static SkIRect PickClipBounds(const SkDraw& draw) {
1497 const SkRasterClip& rasterClip = *draw.fRC;
1498
1499 if (rasterClip.isBW()) {
1500 return rasterClip.bwRgn().getBounds();
1501 } else {
1502 return rasterClip.aaRgn().getBounds();
1503 }
1504 }
1505
1506 bool getImageData(const SkGlyph& glyph, SkMask* mask) {
1507 uint8_t* bits = (uint8_t*)(fGlyphCache->findImage(glyph));
1508 if (nullptr == bits) {
1509 return false; // can't rasterize glyph
1510 }
1511 mask->fImage = bits;
1512 mask->fRowBytes = glyph.rowBytes();
1513 mask->fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1514 return true;
1515 }
1516
1454 void blitMask(const SkMask& mask, const SkIRect& clip) const { 1517 void blitMask(const SkMask& mask, const SkIRect& clip) const {
1455 if (SkMask::kARGB32_Format == mask.fFormat) { 1518 if (SkMask::kARGB32_Format == mask.fFormat) {
1456 this->blitMaskAsSprite(mask); 1519 SkBitmap bm;
1520 bm.installPixels(
1521 SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.he ight()),
1522 (SkPMColor*)mask.fImage, mask.fRowBytes);
1523
1524 fDraw.drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), fPaint);
1457 } else { 1525 } else {
1458 fBlitter->blitMask(mask, clip); 1526 fBlitter->blitMask(mask, clip);
1459 } 1527 }
1460 } 1528 }
1461 1529
1462 // mask must be kARGB32_Format 1530 const bool fUseRegionToDraw;
1463 void blitMaskAsSprite(const SkMask& mask) const; 1531 SkGlyphCache * const fGlyphCache;
1532 SkBlitter * const fBlitter;
1533 const SkRegion* const fClip;
1534 const SkDraw& fDraw;
1535 const SkPaint& fPaint;
1536 const SkIRect fClipBounds;
1464 }; 1537 };
1465 1538
1466 static void D1G_RectClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, 1539 //////////////////////////////////////////////////////////////////////////////// ////////////////////
1467 const SkGlyph& glyph) {
1468 // Prevent glyphs from being drawn outside of or straddling the edge of devi ce space.
1469 if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1470 (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) ||
1471 (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1472 (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/))
1473 {
1474 return;
1475 }
1476
1477 int left = Sk48Dot16FloorToInt(fx);
1478 int top = Sk48Dot16FloorToInt(fy);
1479 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1480 SkASSERT((nullptr == state.fClip && state.fAAClip) ||
1481 (state.fClip && nullptr == state.fAAClip && state.fClip->isRect())) ;
1482
1483 left += glyph.fLeft;
1484 top += glyph.fTop;
1485
1486 int right = left + glyph.fWidth;
1487 int bottom = top + glyph.fHeight;
1488
1489 SkMask mask;
1490 SkIRect storage;
1491 SkIRect* bounds = &mask.fBounds;
1492
1493 mask.fBounds.set(left, top, right, bottom);
1494
1495 // this extra test is worth it, assuming that most of the time it succeeds
1496 // since we can avoid writing to storage
1497 if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
1498 if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
1499 return;
1500 bounds = &storage;
1501 }
1502
1503 uint8_t* aa = (uint8_t*)glyph.fImage;
1504 if (nullptr == aa) {
1505 aa = (uint8_t*)state.fCache->findImage(glyph);
1506 if (nullptr == aa) {
1507 return; // can't rasterize glyph
1508 }
1509 }
1510
1511 mask.fRowBytes = glyph.rowBytes();
1512 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1513 mask.fImage = aa;
1514 state.blitMask(mask, *bounds);
1515 }
1516
1517 static void D1G_RgnClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy,
1518 const SkGlyph& glyph) {
1519 int left = Sk48Dot16FloorToInt(fx);
1520 int top = Sk48Dot16FloorToInt(fy);
1521 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1522 SkASSERT(!state.fClip->isRect());
1523
1524 SkMask mask;
1525
1526 left += glyph.fLeft;
1527 top += glyph.fTop;
1528
1529 mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
1530 SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
1531
1532 if (!clipper.done()) {
1533 const SkIRect& cr = clipper.rect();
1534 const uint8_t* aa = (uint8_t*)state.fCache->findImage(glyph);
1535 if (nullptr == aa) {
1536 return;
1537 }
1538
1539 mask.fRowBytes = glyph.rowBytes();
1540 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1541 mask.fImage = (uint8_t*)aa;
1542 do {
1543 state.blitMask(mask, cr);
1544 clipper.next();
1545 } while (!clipper.done());
1546 }
1547 }
1548
1549 SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, Sk GlyphCache* cache,
1550 const SkPaint& pnt) {
1551 fDraw = draw;
1552 fBlitter = blitter;
1553 fCache = cache;
1554 fPaint = &pnt;
1555
1556 if (cache->isSubpixel()) {
1557 fHalfSampleX = fHalfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
1558 } else {
1559 fHalfSampleX = fHalfSampleY = SK_ScalarHalf;
1560 }
1561
1562 if (draw->fRC->isBW()) {
1563 fAAClip = nullptr;
1564 fClip = &draw->fRC->bwRgn();
1565 fClipBounds = fClip->getBounds();
1566 if (fClip->isRect()) {
1567 return D1G_RectClip;
1568 } else {
1569 return D1G_RgnClip;
1570 }
1571 } else { // aaclip
1572 fAAClip = &draw->fRC->aaRgn();
1573 fClip = nullptr;
1574 fClipBounds = fAAClip->getBounds();
1575 return D1G_RectClip;
1576 }
1577 }
1578
1579 void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
1580 SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
1581
1582 SkBitmap bm;
1583 bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBoun ds.height()),
1584 (SkPMColor*)mask.fImage, mask.fRowBytes);
1585
1586 fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
1587 }
1588
1589 ///////////////////////////////////////////////////////////////////////////////
1590 1540
1591 void SkDraw::drawText(const char text[], size_t byteLength, 1541 void SkDraw::drawText(const char text[], size_t byteLength,
1592 SkScalar x, SkScalar y, const SkPaint& paint) const { 1542 SkScalar x, SkScalar y, const SkPaint& paint) const {
1593 SkASSERT(byteLength == 0 || text != nullptr); 1543 SkASSERT(byteLength == 0 || text != nullptr);
1594 1544
1595 SkDEBUGCODE(this->validate();) 1545 SkDEBUGCODE(this->validate();)
1596 1546
1597 // nothing to draw 1547 // nothing to draw
1598 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 1548 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) {
1599 return; 1549 return;
1600 } 1550 }
1601 1551
1602 // SkScalarRec doesn't currently have a way of representing hairline stroke and 1552 // SkScalarRec doesn't currently have a way of representing hairline stroke and
1603 // will fill if its frame-width is 0. 1553 // will fill if its frame-width is 0.
1604 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 1554 if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1605 this->drawText_asPaths(text, byteLength, x, y, paint); 1555 this->drawText_asPaths(text, byteLength, x, y, paint);
1606 return; 1556 return;
1607 } 1557 }
1608 1558
1609 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); 1559 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
1610 SkGlyphCache* cache = autoCache.getCache(); 1560 SkGlyphCache* cache = autoCache.getCache();
1611
1612 1561
1613 // The Blitter Choose needs to be live while using the blitter below. 1562 // The Blitter Choose needs to be live while using the blitter below.
1614 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 1563 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint);
1615 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1564 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
1616 1565 DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter( ));
1617 SkDraw1Glyph d1g;
1618 SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint );
1619 1566
1620 SkFindAndPlaceGlyph::ProcessText( 1567 SkFindAndPlaceGlyph::ProcessText(
1621 paint.getTextEncoding(), text, byteLength, 1568 paint.getTextEncoding(), text, byteLength,
1622 {x, y}, *fMatrix, paint.getTextAlign(), cache, 1569 {x, y}, *fMatrix, paint.getTextAlign(), cache, drawOneGlyph);
1623 [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
1624 position += rounding;
1625 proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position .fY), glyph);
1626 }
1627 );
1628 } 1570 }
1629 1571
1630 ////////////////////////////////////////////////////////////////////////////// 1572 //////////////////////////////////////////////////////////////////////////////
1631 1573
1632 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, 1574 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
1633 const SkScalar pos[], int scalarsPerPosition, 1575 const SkScalar pos[], int scalarsPerPosition,
1634 const SkPoint& offset, const SkPaint& origPaint ) const { 1576 const SkPoint& offset, const SkPaint& origPaint ) const {
1635 // setup our std paint, in hopes of getting hits in the cache 1577 // setup our std paint, in hopes of getting hits in the cache
1636 SkPaint paint(origPaint); 1578 SkPaint paint(origPaint);
1637 SkScalar matrixScale = paint.setupForAsPaths(); 1579 SkScalar matrixScale = paint.setupForAsPaths();
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1689 // nothing to draw 1631 // nothing to draw
1690 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 1632 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) {
1691 return; 1633 return;
1692 } 1634 }
1693 1635
1694 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 1636 if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1695 this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, off set, paint); 1637 this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, off set, paint);
1696 return; 1638 return;
1697 } 1639 }
1698 1640
1641 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
1642 SkGlyphCache* cache = autoCache.getCache();
1643
1699 // The Blitter Choose needs to be live while using the blitter below. 1644 // The Blitter Choose needs to be live while using the blitter below.
1700 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 1645 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint);
1701 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1646 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
1702 1647 DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter( ));
1703 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); 1648 SkPaint::Align textAlignment = paint.getTextAlign();
1704 SkGlyphCache* cache = autoCache.getCache();
1705 SkDraw1Glyph d1g;
1706 SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint) ;
1707 SkPaint::Align textAlignment = paint.getTextAlign();
1708 1649
1709 SkFindAndPlaceGlyph::ProcessPosText( 1650 SkFindAndPlaceGlyph::ProcessPosText(
1710 paint.getTextEncoding(), text, byteLength, 1651 paint.getTextEncoding(), text, byteLength,
1711 offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache, 1652 offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache, drawOne Glyph);
1712 [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
1713 position += rounding;
1714 proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position .fY), glyph);
1715 }
1716 );
1717 } 1653 }
1718 1654
1719 #if defined _WIN32 && _MSC_VER >= 1300 1655 #if defined _WIN32 && _MSC_VER >= 1300
1720 #pragma warning ( pop ) 1656 #pragma warning ( pop )
1721 #endif 1657 #endif
1722 1658
1723 /////////////////////////////////////////////////////////////////////////////// 1659 ///////////////////////////////////////////////////////////////////////////////
1724 1660
1725 static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) { 1661 static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) {
1726 return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 1662 return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
2109 mask->fImage = SkMask::AllocImage(size); 2045 mask->fImage = SkMask::AllocImage(size);
2110 memset(mask->fImage, 0, mask->computeImageSize()); 2046 memset(mask->fImage, 0, mask->computeImageSize());
2111 } 2047 }
2112 2048
2113 if (SkMask::kJustComputeBounds_CreateMode != mode) { 2049 if (SkMask::kJustComputeBounds_CreateMode != mode) {
2114 draw_into_mask(*mask, devPath, style); 2050 draw_into_mask(*mask, devPath, style);
2115 } 2051 }
2116 2052
2117 return true; 2053 return true;
2118 } 2054 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698