| OLD | NEW |
| 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 Loading... |
| 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; |
| 1426 | 1438 |
| 1427 static void D1G_RectClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy,
const SkGlyph& glyph) { | 1439 /** Draws one glyph. |
| 1440 * |
| 1441 * The x and y are pre-biased, so implementations may just truncate them. |
| 1442 * i.e. half the sampling frequency has been added. |
| 1443 * e.g. 1/2 or 1/(2^(SkGlyph::kSubBits+1)) has already been added. |
| 1444 * This added bias can be found in fHalfSampleX,Y. |
| 1445 */ |
| 1446 typedef void (*Proc)(const SkDraw1Glyph&, Sk48Dot16 x, Sk48Dot16 y, const Sk
Glyph&); |
| 1447 |
| 1448 Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache, |
| 1449 const SkPaint&); |
| 1450 |
| 1451 // call this instead of fBlitter->blitMask() since this wrapper will handle |
| 1452 // the case when the mask is ARGB32_Format |
| 1453 // |
| 1454 void blitMask(const SkMask& mask, const SkIRect& clip) const { |
| 1455 if (SkMask::kARGB32_Format == mask.fFormat) { |
| 1456 this->blitMaskAsSprite(mask); |
| 1457 } else { |
| 1458 fBlitter->blitMask(mask, clip); |
| 1459 } |
| 1460 } |
| 1461 |
| 1462 // mask must be kARGB32_Format |
| 1463 void blitMaskAsSprite(const SkMask& mask) const; |
| 1464 }; |
| 1465 |
| 1466 static void D1G_RectClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, |
| 1467 const SkGlyph& glyph) { |
| 1428 // Prevent glyphs from being drawn outside of or straddling the edge of devi
ce space. | 1468 // Prevent glyphs from being drawn outside of or straddling the edge of devi
ce space. |
| 1429 if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) || | 1469 if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) || |
| 1430 (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) || | 1470 (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) || |
| 1431 (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) || | 1471 (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) || |
| 1432 (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) | 1472 (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) |
| 1433 { | 1473 { |
| 1434 return; | 1474 return; |
| 1435 } | 1475 } |
| 1436 | 1476 |
| 1437 int left = Sk48Dot16FloorToInt(fx); | 1477 int left = Sk48Dot16FloorToInt(fx); |
| (...skipping 29 matching lines...) Expand all Loading... |
| 1467 return; // can't rasterize glyph | 1507 return; // can't rasterize glyph |
| 1468 } | 1508 } |
| 1469 } | 1509 } |
| 1470 | 1510 |
| 1471 mask.fRowBytes = glyph.rowBytes(); | 1511 mask.fRowBytes = glyph.rowBytes(); |
| 1472 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); | 1512 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); |
| 1473 mask.fImage = aa; | 1513 mask.fImage = aa; |
| 1474 state.blitMask(mask, *bounds); | 1514 state.blitMask(mask, *bounds); |
| 1475 } | 1515 } |
| 1476 | 1516 |
| 1477 static void D1G_RgnClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, c
onst SkGlyph& glyph) { | 1517 static void D1G_RgnClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy, |
| 1518 const SkGlyph& glyph) { |
| 1478 int left = Sk48Dot16FloorToInt(fx); | 1519 int left = Sk48Dot16FloorToInt(fx); |
| 1479 int top = Sk48Dot16FloorToInt(fy); | 1520 int top = Sk48Dot16FloorToInt(fy); |
| 1480 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); | 1521 SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0); |
| 1481 SkASSERT(!state.fClip->isRect()); | 1522 SkASSERT(!state.fClip->isRect()); |
| 1482 | 1523 |
| 1483 SkMask mask; | 1524 SkMask mask; |
| 1484 | 1525 |
| 1485 left += glyph.fLeft; | 1526 left += glyph.fLeft; |
| 1486 top += glyph.fTop; | 1527 top += glyph.fTop; |
| 1487 | 1528 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1498 mask.fRowBytes = glyph.rowBytes(); | 1539 mask.fRowBytes = glyph.rowBytes(); |
| 1499 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); | 1540 mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat); |
| 1500 mask.fImage = (uint8_t*)aa; | 1541 mask.fImage = (uint8_t*)aa; |
| 1501 do { | 1542 do { |
| 1502 state.blitMask(mask, cr); | 1543 state.blitMask(mask, cr); |
| 1503 clipper.next(); | 1544 clipper.next(); |
| 1504 } while (!clipper.done()); | 1545 } while (!clipper.done()); |
| 1505 } | 1546 } |
| 1506 } | 1547 } |
| 1507 | 1548 |
| 1508 static bool hasCustomD1GProc(const SkDraw& draw) { | |
| 1509 return draw.fProcs && draw.fProcs->fD1GProc; | |
| 1510 } | |
| 1511 | |
| 1512 static bool needsRasterTextBlit(const SkDraw& draw) { | |
| 1513 return !hasCustomD1GProc(draw); | |
| 1514 } | |
| 1515 | |
| 1516 SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, Sk
GlyphCache* cache, | 1549 SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, Sk
GlyphCache* cache, |
| 1517 const SkPaint& pnt) { | 1550 const SkPaint& pnt) { |
| 1518 fDraw = draw; | 1551 fDraw = draw; |
| 1519 fBlitter = blitter; | 1552 fBlitter = blitter; |
| 1520 fCache = cache; | 1553 fCache = cache; |
| 1521 fPaint = &pnt; | 1554 fPaint = &pnt; |
| 1522 | 1555 |
| 1523 if (cache->isSubpixel()) { | 1556 if (cache->isSubpixel()) { |
| 1524 fHalfSampleX = fHalfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound); | 1557 fHalfSampleX = fHalfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound); |
| 1525 } else { | 1558 } else { |
| 1526 fHalfSampleX = fHalfSampleY = SK_ScalarHalf; | 1559 fHalfSampleX = fHalfSampleY = SK_ScalarHalf; |
| 1527 } | 1560 } |
| 1528 | 1561 |
| 1529 if (hasCustomD1GProc(*draw)) { | |
| 1530 // todo: fix this assumption about clips w/ custom | |
| 1531 fClip = draw->fClip; | |
| 1532 fClipBounds = fClip->getBounds(); | |
| 1533 return draw->fProcs->fD1GProc; | |
| 1534 } | |
| 1535 | |
| 1536 if (draw->fRC->isBW()) { | 1562 if (draw->fRC->isBW()) { |
| 1537 fAAClip = nullptr; | 1563 fAAClip = nullptr; |
| 1538 fClip = &draw->fRC->bwRgn(); | 1564 fClip = &draw->fRC->bwRgn(); |
| 1539 fClipBounds = fClip->getBounds(); | 1565 fClipBounds = fClip->getBounds(); |
| 1540 if (fClip->isRect()) { | 1566 if (fClip->isRect()) { |
| 1541 return D1G_RectClip; | 1567 return D1G_RectClip; |
| 1542 } else { | 1568 } else { |
| 1543 return D1G_RgnClip; | 1569 return D1G_RgnClip; |
| 1544 } | 1570 } |
| 1545 } else { // aaclip | 1571 } else { // aaclip |
| (...skipping 30 matching lines...) Expand all Loading... |
| 1576 // SkScalarRec doesn't currently have a way of representing hairline stroke
and | 1602 // SkScalarRec doesn't currently have a way of representing hairline stroke
and |
| 1577 // will fill if its frame-width is 0. | 1603 // will fill if its frame-width is 0. |
| 1578 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { | 1604 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { |
| 1579 this->drawText_asPaths(text, byteLength, x, y, paint); | 1605 this->drawText_asPaths(text, byteLength, x, y, paint); |
| 1580 return; | 1606 return; |
| 1581 } | 1607 } |
| 1582 | 1608 |
| 1583 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); | 1609 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); |
| 1584 SkGlyphCache* cache = autoCache.getCache(); | 1610 SkGlyphCache* cache = autoCache.getCache(); |
| 1585 | 1611 |
| 1586 SkAAClipBlitter aaBlitter; | 1612 |
| 1587 SkAutoBlitterChoose blitterChooser; | 1613 // The Blitter Choose needs to be live while using the blitter below. |
| 1588 SkBlitter* blitter = nullptr; | 1614 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); |
| 1589 if (needsRasterTextBlit(*this)) { | 1615 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); |
| 1590 blitterChooser.choose(fDst, *fMatrix, paint); | |
| 1591 blitter = blitterChooser.get(); | |
| 1592 if (fRC->isAA()) { | |
| 1593 aaBlitter.init(blitter, &fRC->aaRgn()); | |
| 1594 blitter = &aaBlitter; | |
| 1595 } | |
| 1596 } | |
| 1597 | 1616 |
| 1598 SkDraw1Glyph d1g; | 1617 SkDraw1Glyph d1g; |
| 1599 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); | 1618 SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint
); |
| 1600 | 1619 |
| 1601 SkFindAndPlaceGlyph::ProcessText( | 1620 SkFindAndPlaceGlyph::ProcessText( |
| 1602 paint.getTextEncoding(), text, byteLength, | 1621 paint.getTextEncoding(), text, byteLength, |
| 1603 {x, y}, *fMatrix, paint.getTextAlign(), cache, | 1622 {x, y}, *fMatrix, paint.getTextAlign(), cache, |
| 1604 [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { | 1623 [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { |
| 1605 position += rounding; | 1624 position += rounding; |
| 1606 proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position
.fY), glyph); | 1625 proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position
.fY), glyph); |
| 1607 } | 1626 } |
| 1608 ); | 1627 ); |
| 1609 } | 1628 } |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1671 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { | 1690 if (text == nullptr || byteLength == 0 || fRC->isEmpty()) { |
| 1672 return; | 1691 return; |
| 1673 } | 1692 } |
| 1674 | 1693 |
| 1675 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { | 1694 if (ShouldDrawTextAsPaths(paint, *fMatrix)) { |
| 1676 this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, off
set, paint); | 1695 this->drawPosText_asPaths(text, byteLength, pos, scalarsPerPosition, off
set, paint); |
| 1677 return; | 1696 return; |
| 1678 } | 1697 } |
| 1679 | 1698 |
| 1680 // The Blitter Choose needs to be live while using the blitter below. | 1699 // The Blitter Choose needs to be live while using the blitter below. |
| 1681 SkAutoBlitterChoose blitterChooser; | 1700 SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint); |
| 1682 SkAAClipBlitterWrapper wrapper; | 1701 SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get()); |
| 1683 SkBlitter* blitter = nullptr; | |
| 1684 if (needsRasterTextBlit(*this)) { | |
| 1685 blitterChooser.choose(fDst, *fMatrix, paint); | |
| 1686 blitter = blitterChooser.get(); | |
| 1687 if (fRC->isAA()) { | |
| 1688 wrapper.init(*fRC, blitter); | |
| 1689 blitter = wrapper.getBlitter(); | |
| 1690 } | |
| 1691 } | |
| 1692 | 1702 |
| 1693 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); | 1703 SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix); |
| 1694 SkGlyphCache* cache = autoCache.getCache(); | 1704 SkGlyphCache* cache = autoCache.getCache(); |
| 1695 SkDraw1Glyph d1g; | 1705 SkDraw1Glyph d1g; |
| 1696 SkDraw1Glyph::Proc proc = d1g.init(this, blitter, cache, paint); | 1706 SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint)
; |
| 1697 SkPaint::Align textAlignment = paint.getTextAlign(); | 1707 SkPaint::Align textAlignment = paint.getTextAlign(); |
| 1698 | 1708 |
| 1699 SkFindAndPlaceGlyph::ProcessPosText( | 1709 SkFindAndPlaceGlyph::ProcessPosText( |
| 1700 paint.getTextEncoding(), text, byteLength, | 1710 paint.getTextEncoding(), text, byteLength, |
| 1701 offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache, | 1711 offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache, |
| 1702 [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { | 1712 [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { |
| 1703 position += rounding; | 1713 position += rounding; |
| 1704 proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position
.fY), glyph); | 1714 proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position
.fY), glyph); |
| 1705 } | 1715 } |
| 1706 ); | 1716 ); |
| (...skipping 392 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2099 mask->fImage = SkMask::AllocImage(size); | 2109 mask->fImage = SkMask::AllocImage(size); |
| 2100 memset(mask->fImage, 0, mask->computeImageSize()); | 2110 memset(mask->fImage, 0, mask->computeImageSize()); |
| 2101 } | 2111 } |
| 2102 | 2112 |
| 2103 if (SkMask::kJustComputeBounds_CreateMode != mode) { | 2113 if (SkMask::kJustComputeBounds_CreateMode != mode) { |
| 2104 draw_into_mask(*mask, devPath, style); | 2114 draw_into_mask(*mask, devPath, style); |
| 2105 } | 2115 } |
| 2106 | 2116 |
| 2107 return true; | 2117 return true; |
| 2108 } | 2118 } |
| OLD | NEW |