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

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

Issue 1507633004: Simplify D1G so that it can inline DrawOneGlyph, and fix a bug in codegen (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: delete line 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 | src/core/SkFindAndPlaceGlyph.h » ('j') | 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 22 matching lines...) Expand all
33 #include "SkUtility.h" 33 #include "SkUtility.h"
34 #include "SkUtils.h" 34 #include "SkUtils.h"
35 #include "SkVertState.h" 35 #include "SkVertState.h"
36 36
37 #include "SkBitmapProcShader.h" 37 #include "SkBitmapProcShader.h"
38 #include "SkDrawProcs.h" 38 #include "SkDrawProcs.h"
39 #include "SkMatrixUtils.h" 39 #include "SkMatrixUtils.h"
40 40
41 //#define TRACE_BITMAP_DRAWS 41 //#define TRACE_BITMAP_DRAWS
42 42
43 // Helper function to fix code gen bug on ARM64.
44 // See SkFindAndPlaceGlyph.h for more details.
45 void FixGCC49Arm64Bug(int v) { }
43 46
44 /** Helper for allocating small blitters on the stack. 47 /** Helper for allocating small blitters on the stack.
45 */ 48 */
46 class SkAutoBlitterChoose : SkNoncopyable { 49 class SkAutoBlitterChoose : SkNoncopyable {
47 public: 50 public:
48 SkAutoBlitterChoose() { 51 SkAutoBlitterChoose() {
49 fBlitter = nullptr; 52 fBlitter = nullptr;
50 } 53 }
51 SkAutoBlitterChoose(const SkPixmap& dst, const SkMatrix& matrix, 54 SkAutoBlitterChoose(const SkPixmap& dst, const SkMatrix& matrix,
52 const SkPaint& paint, bool drawCoverage = false) { 55 const SkPaint& paint, bool drawCoverage = false) {
(...skipping 1363 matching lines...) Expand 10 before | Expand all | Expand 10 after
1416 } 1419 }
1417 } 1420 }
1418 1421
1419 // disable warning : local variable used without having been initialized 1422 // disable warning : local variable used without having been initialized
1420 #if defined _WIN32 && _MSC_VER >= 1300 1423 #if defined _WIN32 && _MSC_VER >= 1300
1421 #pragma warning ( push ) 1424 #pragma warning ( push )
1422 #pragma warning ( disable : 4701 ) 1425 #pragma warning ( disable : 4701 )
1423 #endif 1426 #endif
1424 1427
1425 //////////////////////////////////////////////////////////////////////////////// //////////////////// 1428 //////////////////////////////////////////////////////////////////////////////// ////////////////////
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 1429
1439 /** Draws one glyph. 1430 class DrawOneGlyph {
1440 * 1431 public:
1441 * The x and y are pre-biased, so implementations may just truncate them. 1432 DrawOneGlyph(const SkDraw& draw, const SkPaint& paint, SkGlyphCache* cache, SkBlitter* blitter)
1442 * i.e. half the sampling frequency has been added. 1433 : fUseRegionToDraw(UsingRegionToDraw(draw.fRC))
1443 * e.g. 1/2 or 1/(2^(SkGlyph::kSubBits+1)) has already been added. 1434 , fGlyphCache(cache)
1444 * This added bias can be found in fHalfSampleX,Y. 1435 , fBlitter(blitter)
1445 */ 1436 , fClip(fUseRegionToDraw ? &draw.fRC->bwRgn() : nullptr)
1446 typedef void (*Proc)(const SkDraw1Glyph&, Sk48Dot16 x, Sk48Dot16 y, const Sk Glyph&); 1437 , fDraw(draw)
1438 , fPaint(paint)
1439 , fClipBounds(PickClipBounds(draw)) { }
1447 1440
1448 Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache, 1441 void operator()(const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
1449 const SkPaint&); 1442 position += rounding;
1443 Sk48Dot16 fx = SkScalarTo48Dot16(position.fX);
1444 Sk48Dot16 fy = SkScalarTo48Dot16(position.fY);
1445 // Prevent glyphs from being drawn outside of or straddling the edge of device space.
1446 if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1447 (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) ||
1448 (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
1449 (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) {
1450 return;
1451 }
1450 1452
1451 // call this instead of fBlitter->blitMask() since this wrapper will handle 1453 int left = Sk48Dot16FloorToInt(fx);
1452 // the case when the mask is ARGB32_Format 1454 int top = Sk48Dot16FloorToInt(fy);
1453 // 1455 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
1456
1457 left += glyph.fLeft;
1458 top += glyph.fTop;
1459
1460 int right = left + glyph.fWidth;
1461 int bottom = top + glyph.fHeight;
1462
1463 SkMask mask;
1464 mask.fBounds.set(left, top, right, bottom);
1465
1466 if (fUseRegionToDraw) {
1467 SkRegion::Cliperator clipper(*fClip, mask.fBounds);
1468
1469 if (!clipper.done() && this->getImageData(glyph, &mask)) {
1470 const SkIRect& cr = clipper.rect();
1471 do {
1472 this->blitMask(mask, cr);
1473 clipper.next();
1474 } while (!clipper.done());
1475 }
1476 } else {
1477 SkIRect storage;
1478 SkIRect* bounds = &mask.fBounds;
1479
1480 // this extra test is worth it, assuming that most of the time it su cceeds
1481 // since we can avoid writing to storage
1482 if (!fClipBounds.containsNoEmptyCheck(mask.fBounds)) {
1483 if (!storage.intersectNoEmptyCheck(mask.fBounds, fClipBounds))
1484 return;
1485 bounds = &storage;
1486 }
1487
1488 if (this->getImageData(glyph, &mask)) {
1489 this->blitMask(mask, *bounds);
1490 }
1491 }
1492 }
1493
1494 private:
1495 static bool UsingRegionToDraw(const SkRasterClip* rClip) {
1496 return rClip->isBW() && !rClip->isRect();
1497 }
1498
1499 static SkIRect PickClipBounds(const SkDraw& draw) {
1500 const SkRasterClip& rasterClip = *draw.fRC;
1501
1502 if (rasterClip.isBW()) {
1503 return rasterClip.bwRgn().getBounds();
1504 } else {
1505 return rasterClip.aaRgn().getBounds();
1506 }
1507 }
1508
1509 bool getImageData(const SkGlyph& glyph, SkMask* mask) {
1510 uint8_t* bits = (uint8_t*)(fGlyphCache->findImage(glyph));
1511 if (nullptr == bits) {
1512 return false; // can't rasterize glyph
1513 }
1514 mask->fImage = bits;
1515 mask->fRowBytes = glyph.rowBytes();
1516 mask->fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
1517 return true;
1518 }
1519
1454 void blitMask(const SkMask& mask, const SkIRect& clip) const { 1520 void blitMask(const SkMask& mask, const SkIRect& clip) const {
1455 if (SkMask::kARGB32_Format == mask.fFormat) { 1521 if (SkMask::kARGB32_Format == mask.fFormat) {
1456 this->blitMaskAsSprite(mask); 1522 SkBitmap bm;
1523 bm.installPixels(
1524 SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.he ight()),
1525 (SkPMColor*)mask.fImage, mask.fRowBytes);
1526
1527 fDraw.drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), fPaint);
1457 } else { 1528 } else {
1458 fBlitter->blitMask(mask, clip); 1529 fBlitter->blitMask(mask, clip);
1459 } 1530 }
1460 } 1531 }
1461 1532
1462 // mask must be kARGB32_Format 1533 const bool fUseRegionToDraw;
1463 void blitMaskAsSprite(const SkMask& mask) const; 1534 SkGlyphCache * const fGlyphCache;
1535 SkBlitter * const fBlitter;
1536 const SkRegion* const fClip;
1537 const SkDraw& fDraw;
1538 const SkPaint& fPaint;
1539 const SkIRect fClipBounds;
1464 }; 1540 };
1465 1541
1466 static void D1G_RectClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, 1542 //////////////////////////////////////////////////////////////////////////////// ////////////////////
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 1543
1591 void SkDraw::drawText(const char text[], size_t byteLength, 1544 void SkDraw::drawText(const char text[], size_t byteLength,
1592 SkScalar x, SkScalar y, const SkPaint& paint) const { 1545 SkScalar x, SkScalar y, const SkPaint& paint) const {
1593 SkASSERT(byteLength == 0 || text != nullptr); 1546 SkASSERT(byteLength == 0 || text != nullptr);
1594 1547
1595 SkDEBUGCODE(this->validate();) 1548 SkDEBUGCODE(this->validate();)
1596 1549
1597 // nothing to draw 1550 // nothing to draw
1598 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 1551 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) {
1599 return; 1552 return;
1600 } 1553 }
1601 1554
1602 // SkScalarRec doesn't currently have a way of representing hairline stroke and 1555 // SkScalarRec doesn't currently have a way of representing hairline stroke and
1603 // will fill if its frame-width is 0. 1556 // will fill if its frame-width is 0.
1604 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 1557 if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1605 this->drawText_asPaths(text, byteLength, x, y, paint); 1558 this->drawText_asPaths(text, byteLength, x, y, paint);
1606 return; 1559 return;
1607 } 1560 }
1608 1561
1609 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); 1562 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
1610 SkGlyphCache* cache = autoCache.getCache(); 1563 SkGlyphCache* cache = autoCache.getCache();
1611
1612 1564
1613 // The Blitter Choose needs to be live while using the blitter below. 1565 // The Blitter Choose needs to be live while using the blitter below.
1614 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 1566 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint);
1615 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1567 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
1616 1568 DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter( ));
1617 SkDraw1Glyph d1g;
1618 SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint );
1619 1569
1620 SkFindAndPlaceGlyph::ProcessText( 1570 SkFindAndPlaceGlyph::ProcessText(
1621 paint.getTextEncoding(), text, byteLength, 1571 paint.getTextEncoding(), text, byteLength,
1622 {x, y}, *fMatrix, paint.getTextAlign(), cache, 1572 {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 } 1573 }
1629 1574
1630 ////////////////////////////////////////////////////////////////////////////// 1575 //////////////////////////////////////////////////////////////////////////////
1631 1576
1632 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength, 1577 void SkDraw::drawPosText_asPaths(const char text[], size_t byteLength,
1633 const SkScalar pos[], int scalarsPerPosition, 1578 const SkScalar pos[], int scalarsPerPosition,
1634 const SkPoint& offset, const SkPaint& origPaint ) const { 1579 const SkPoint& offset, const SkPaint& origPaint ) const {
1635 // setup our std paint, in hopes of getting hits in the cache 1580 // setup our std paint, in hopes of getting hits in the cache
1636 SkPaint paint(origPaint); 1581 SkPaint paint(origPaint);
1637 SkScalar matrixScale = paint.setupForAsPaths(); 1582 SkScalar matrixScale = paint.setupForAsPaths();
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1689 // nothing to draw 1634 // nothing to draw
1690 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { 1635 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) {
1691 return; 1636 return;
1692 } 1637 }
1693 1638
1694 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { 1639 if (ShouldDrawTextAsPaths(paint, *fMatrix)) {
1695 this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, off set, paint); 1640 this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, off set, paint);
1696 return; 1641 return;
1697 } 1642 }
1698 1643
1644 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
1645 SkGlyphCache* cache = autoCache.getCache();
1646
1699 // The Blitter Choose needs to be live while using the blitter below. 1647 // The Blitter Choose needs to be live while using the blitter below.
1700 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); 1648 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint);
1701 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); 1649 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
1702 1650 DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter( ));
1703 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); 1651 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 1652
1709 SkFindAndPlaceGlyph::ProcessPosText( 1653 SkFindAndPlaceGlyph::ProcessPosText(
1710 paint.getTextEncoding(), text, byteLength, 1654 paint.getTextEncoding(), text, byteLength,
1711 offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache, 1655 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 } 1656 }
1718 1657
1719 #if defined _WIN32 && _MSC_VER >= 1300 1658 #if defined _WIN32 && _MSC_VER >= 1300
1720 #pragma warning ( pop ) 1659 #pragma warning ( pop )
1721 #endif 1660 #endif
1722 1661
1723 /////////////////////////////////////////////////////////////////////////////// 1662 ///////////////////////////////////////////////////////////////////////////////
1724 1663
1725 static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) { 1664 static SkScan::HairRCProc ChooseHairProc(bool doAntiAlias) {
1726 return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine; 1665 return doAntiAlias ? SkScan::AntiHairLine : SkScan::HairLine;
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
2109 mask->fImage = SkMask::AllocImage(size); 2048 mask->fImage = SkMask::AllocImage(size);
2110 memset(mask->fImage, 0, mask->computeImageSize()); 2049 memset(mask->fImage, 0, mask->computeImageSize());
2111 } 2050 }
2112 2051
2113 if (SkMask::kJustComputeBounds_CreateMode != mode) { 2052 if (SkMask::kJustComputeBounds_CreateMode != mode) {
2114 draw_into_mask(*mask, devPath, style); 2053 draw_into_mask(*mask, devPath, style);
2115 } 2054 }
2116 2055
2117 return true; 2056 return true;
2118 } 2057 }
OLDNEW
« no previous file with comments | « no previous file | src/core/SkFindAndPlaceGlyph.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698